10

I have a script that should only be run with Python 3. I want to give a nice error message saying that this script should not be run with python2 if a user tries to run it with Python 2.x

How do I do this? When I try checking the Python version, it still throws an error, as Python parses the whole file before executing my if condition.

If possible, I'd rather not make another script.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
AbdealiLoKo
  • 3,261
  • 2
  • 20
  • 36
  • 3
    If it's a `SyntaxError`, you can't avoid it; as you say, the error comes *before* any code you've written runs. You have to write code that is *syntactically valid* in both versions. – jonrsharpe Jul 06 '15 at 08:24
  • You need to first fix your syntax error, then worry about version checking. – Burhan Khalid Jul 06 '15 at 08:28
  • There are some interesting ideas in [How can I check for Python version in a program that uses new language features?](http://stackoverflow.com/questions/446052/how-can-i-check-for-python-version-in-a-program-that-uses-new-language-features) – PM 2Ring Jul 06 '15 at 08:29
  • 2
    @BurhanKhalid: The script uses Python 3 features that are illegal in Python 2, so the syntax errors are _only_ syntax errors to the Python 2 interpreter. Someone writing in Python 3 shouldn't be obliged to write code that is also legal in Python 2. – PM 2Ring Jul 06 '15 at 08:31
  • 1
    @PM2Ring they should if they *want it to run in 2.x*! Even though it's only to customise the error message... – jonrsharpe Jul 06 '15 at 08:33
  • @user3212182 neither you nor the OP should be adding answers to the question. If you have a different solution, *write your own answer*. – jonrsharpe Jul 06 '15 at 11:13

5 Answers5

13

You can write a wrapper start-script in which you only import your actual script and catch for syntax errors:

try:
    import real_module
except SyntaxError:
    print('You need to run this with Python 3')

Then, when real_module.py uses Python 3 syntax that would throw an exception when used with Python 3, the above message is printed out instead.

Of course, instead of just importing the script, you could also first check the version, and then import it when the version is 3. This has the benefit that you will still see syntax errors of your actual script even when you run it with Python 3:

import sys
if sys.version_info[0] < 3:
    print('You need to run this with Python 3')
    sys.exit(1)

import real_module
poke
  • 369,085
  • 72
  • 557
  • 602
  • Was hoping for a method without making another script. Isnt it possible to do it with 1 script ? – AbdealiLoKo Jul 06 '15 at 08:40
  • 2
    No, as others said in the comments, the whole script is parsed before the interpreter runs any code. So a syntax error would throw before any code you could possibly add there will run. – poke Jul 06 '15 at 08:45
  • 1
    @AJK this is your only option, for all of the reasons that have already been explained to you. – jonrsharpe Jul 06 '15 at 09:09
2

None of these properly work as, as others have mentioned SyntaxErrors are parsed first, also doing except SyntaxError does not work either.

The best solution is a wrapper module, but if due to other technical or political reasons you cannot create another module in your code you can do the following very dirty trick:

z, *y=1,2,3,4 #This script requires requires python 3! A Syntax error here means you are running it in python2!

The result in python2.7 will be:

  File "notpython2.py", line 3
    z, *y=1,2,3,4 #This script requires requires python 3! A Syntax error here means you are running it in python2!
       ^
SyntaxError: invalid syntax

Yes the code is ugly, but if anyone can think of a better solution notwithstanding a new module please add it here.

  • 1
    Thank you for this idea. Just today I got a report about an error with my script and it took me too long to figure out that Python 2 was the reason. I *really* didn't want to have to distribute 2 files to handle this, and this solution would make it so an error report would hit me over the head with the answer (heck , many users might figure it out for themselves). I used a slightly more in-your-face version: `Python_2_is_running, *Python_3_is_needed=["py3", "needed"] # this script needs to be run with python 3` – Michael Burr Dec 09 '21 at 23:49
  • 1
    Probably not the place for this comment, but I think the python devs should make one more rev to python2 so that *it* looks for a shebang and if it's `#!python3` or some reasonable variant then the interpreter can give a nice error message. It's hard for me to understand why that wasn't done long ago. – Michael Burr Dec 09 '21 at 23:53
  • @MichaelBurr A good Idea, although from what I have seen, a lot of python scripts seem to not have a shebang, it seems to be an unofficial convention. On the point of a final python2 update, most environments could still be running python2 because they will not / cannot update their python interpreter in the first place, so it may make no difference at all. – Benjamin Goodacre Feb 09 '23 at 12:24
1

Try this:

import sys
#sys.version gives you version number in this format
#(2, 5, 2, 'final', 0)
version=sys.version_info[0]

if version == 2:
   sys.exit("This script shouldn't be run by python 2 ")
1
import sys
if (sys.version_info > (2, 0)):
   raise Exception('script should not be run with python2.x')

This will raise error if script is running under 2.x python version

Abey
  • 1,408
  • 11
  • 26
shashank verma
  • 303
  • 1
  • 3
  • 9
0

You can use the fact that in Python 2 strings are byte strings, while in Python 3 they are unicode strings. So any of

if ' ' == b' ':
    raise Exception ('Running this script with Python 2 is not supported')

or

if isinstance (b' ', str):
    raise Exception ('Running this script with Python 2 is not supported')

will do. Note that this does not need any imports - just language features.

Adrian W
  • 4,563
  • 11
  • 38
  • 52