3

I want to require Python v3.6+ for my command-line script. I have a script named quit_on_27.py as follows:

import sys

if sys.version_info < (3, 6):
    sys.exit("Please use Python 3.6+")


def hello(name:str):
    print(f'Hello, {name}!')


if __name__ == '__main__':
    hello('Jon')

When I run this as a script using Python 2.7:

> python .\quit_on_27.py
  File ".\quit_on_27.py", line 7
    def hello(name:str):
                  ^
SyntaxError: invalid syntax

I also have the same SyntaxError when I use assert sys.version_info >= (3, 6) as mentioned in How do I check what version of Python is running my script? in place of my conditional above.

I'd like to use typing and f-strings and other features not available in Python 2.7, and I'd like to let users know to use a newer version of Python rather than just seeing a SyntaxError.

How do I get this script to exit gracefully and helpfully?

This is more specific than How can I have a python script safely exit itself? since I am asking why my conditional doesn't work as I intended based on the version of Python running the script.

Note: my script does run as intended in Python 3.6.

martineau
  • 119,623
  • 25
  • 170
  • 301
Reid
  • 85
  • 8
  • The main modules needs to have Python 2 compatible syntax all through. But after the check you can **import** Python 3 only modules. – Klaus D. Jun 18 '20 at 17:34
  • @KlausD. I don't quite understand what you mean by the "main modules." I'm only importing `sys`. Where would I put my `hello()` function so that I can check the version of Python? edit: typo – Reid Jun 18 '20 at 17:43
  • 1
    If you want to have a Python 2 compatible version check, then the module you are starting has to be in Python 2 compatible syntax. You can put you functions that are not Python 2 compatible in an extra module and import them after the check. – Klaus D. Jun 18 '20 at 17:48
  • 1
    The problem is due to a syntax difference. One way to avoid the error would be to put the offending code in a separate module and not `import` that module if the version is less than the minimum one that supports it. – martineau Jun 18 '20 at 17:48
  • @martineau, Klaus D. I think you both answered my question at the same time. I'm not sure what the etiquette calls for but I'm happy to accept either one of your comments if entered as an answer. edit: typo – Reid Jun 18 '20 at 17:52

1 Answers1

2

As I (and @Klaus D.) suggested, one way to handle situations like this where the syntax being used is incompatible with earlier versions of the interpeter, would be to put the code using the syntax into a different script and only import it if the version is equal to or higher than the minimum needed.

That said, yet another way to do it is to "hide" the offending code in a string and only execute that string if the version check passes:

Here's what I mean:

import sys

if sys.version_info < (3, 6):
    sys.exit("Please use Python 3.6+")

exec("""
    def hello(name:str):
        print(f'Hello, {name}!')
""")

if __name__ == '__main__':
    hello('Jon')

This latter method may not be compatible with other tools you may be using (like mypy) depending on how "smart" they are…

martineau
  • 119,623
  • 25
  • 170
  • 301