This is one of the practical limitations of recursion without tail call optimization.
Python has a guard against the number of recursive calls you can make in order to avoid a stack overflow. This is the RecursionError you are seeing:
Python 3.7.4 (default, Aug 13 2019, 20:35:49) 
[GCC 7.3.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> def recursion(n):
...     return 1 if n < 2 else n * recursion(n - 2)
... 
>>> 
>>> string = str(recursion(1000000000000000000))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in recursion
  File "<stdin>", line 2, in recursion
  File "<stdin>", line 2, in recursion
  [Previous line repeated 996 more times]
RecursionError: maximum recursion depth exceeded in comparison
Increasing is a possible solution, but it only removes the built-in guard. If enough recursive calls are made, you will eventually run out of memory, which is the second error you are getting (MemoryError: Stack overflow or a segmentation fault in my case).
Python 3.7.4 (default, Aug 13 2019, 20:35:49) 
[GCC 7.3.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.setrecursionlimit(100000)
>>> def recursion(n):
...     return 1 if n < 2 else n * recursion(n - 2)
... 
>>> string = str(recursion(1000000000000000000))
Segmentation fault
The idiomatic solution to this problem in Python would be to use iteration instead:
def iteration(n):
    result = 1
    for i in range(n, 1, -2):
        result *= i
    return result
Running this example with your original input (1e18) won't terminate any time soon though. As the integer grows, it takes increasingly more time to compute, because the operations require using integer representations larger than 64-bit (or however many bits your CPU is able to represent with a single register).
Nevertheless, that would be the Pythonic solution to this problem.