Is there a way to prevent a python 3 script from being called in python 2?
Asked Answered
P

4

11

I have to turn in an assignment, and I'm extremely concerned that, since the single TA has many projects to run, it will be called using python, which will call python 2.7, when the program is written for python3.2 and should be called that way. This would result in a syntax error, and I would loose points. I know when working on side projects, this happens a lot, and if the TA encountered this I don't think he would follow up.

I'm going to submit a readme, but I was wondering if there was a way to catch this in my code without a lot of fuss, and print a statement that said to rerun the project as python3.2 project.py. I could to a try: print "Rerun project…" except:pass, but is there a better way?

Permanence answered 2/4, 2014 at 22:38 Comment(2)
If your class is using python, and hasn't specified if they're using Python 2 or Python 3, then you have bigger problems than that.Nicolettenicoli
@Nicolettenicoli My project can be written in whatever I'd like, and I chose pythonPermanence
S
11

You can do:

import sys
print(sys.version_info)

As of Python 2.7 you can also use:

print(sys.version_info.major, sys.version_info.minor, sys.version_info.micro)

You can use the value of sys.version_info to print a warning when the Python version currently running isn't as desired.

You can also use:

import platform
print(platform.python_version())
Stretch answered 2/4, 2014 at 22:41 Comment(8)
although since the OP wants to run using Py3, you should probably use print()Booth
How would I stop it from running once started though?Permanence
@JFA: you can call sys.exit(0) to exit the execution of the Python code.Stretch
Or throw an exception with a descriptive error message.Nicolettenicoli
One other thing the OP will have to avoid is any Python-3 specific syntax, like x, *y = range(3), for example. That will cause a SyntaxError before any code is even executed.Kamerun
or call sys.exit('Please run this program with Python 3.2') to exit and explain why, all at once.Bantling
I see, I can call sys.version_info.major and if it's not 3 throw an exception or exit.Permanence
My python 2 version returns a SyntaxError for a syntax specific to Python 3, even tough the file starts by checking the python versionChandrachandragupta
F
7

How about starting the program like so:

#!/usr/bin/env python
# -*- coding: utf8 -*-

import sys

if sys.version_info < (3,0,0):
    print(__file__ + ' requires Python 3, while Python ' + str(sys.version[0] + ' was detected. Terminating. '))
    sys.exit(1)
Frankfurter answered 9/7, 2019 at 15:58 Comment(1)
This is a great suggestion. I figured there was a clean, not hacky way of doing this natively.Permanence
S
5

This is actually a harder problem to implement well that you might at first think.

Suppose you have the following code:

import platform
import sys

if platform.python_version().startswith('2'):
    # This NEVER will be executed no matter the version of Python
    # because of the two syntax errors below...
    sys.stdout.write("You're using python 2.x! Python 3.2+ required!!!")
    sys.exit()     
else:
    # big program or def main(): and calling main() .. whatever
    # later in that file/module:
    x, *y=(1,2,3)      # syntax error on Python 2...
    # or
    print 'test'       # syntax error on Python 3...

One of the two syntax errors under the else clause is generated BEFORE the if is actually executed no matter the version of Python used to run it. Therefore, the program will not gracefully exit as you might expect; it will fail with a syntax error no matter what.

The workaround is to put your actual program in an external file/module and wrap in a try/except this way:

try:
    import Py3program    # make sure it has syntax guaranteed to fail on 
                         # Python 2 like    x, *y=1,2,3
except SyntaxError:
    sys.stdout.write(error message)
    sys.exit()

# rest of the Python 3 program...

If your TA will execute the file with a shebang, that would be a better approach still. Perhaps ask the TA how he will run your script?

Shelba answered 3/4, 2014 at 18:51 Comment(3)
They just compile and run them from the command prompt. the concern is that he would run python script and see a bunch of errors when really he was calling the wrong interpreter.Permanence
This except does not seem to work, I still get the SyntaxError: invalid syntax error despite using it on python2.7.16Hemstitch
rest of the Python 3 program... - Wait, but if the rest of the program has syntax that's not valid for Python 2, the error will still happen at compile time instead of runtime. Also, that comment contradicts the description, so... it shouldn't be there, right?Imprest
H
0

Ten years later, this old chestnut still bites. In my case, the python2 interpreter itself stopped the script from running due to a SyntaxError at line 434. Alas, the Error wasn't very informative, and because the script never ran at all, platform.python_version() never ran either. Hence platform tests were no help

Since I didn't want the file to run in python2 anyway, I just added a comment to the line in question, so the SyntaxError looks like:

$ python2 alarm_clock.py
  File "alarm_clock.py", line 434
    txt=f"The time is %M minutes past %{AUDIO_H} o'clock" # <- YOU NEED PYTHON3.6+ IF YOU ARE SEEING THIS IN AN ERROR.
                                                        ^
SyntaxError: invalid syntax

On wjandrea's advice I instead put the following line near the top of my code:

f'' # YOU NEED PYTHON 3.6+. TRY: python3 alarm_clock.py

This had three advantages:

  1. Pylint doesn't complain about a too long line
  2. Less distractions in the error message.
  3. Less likely to disappear due to having another python3-ism added above the comment.
Hypso answered 8/8 at 2:31 Comment(1)
Instead of at a random spot, you could put a f'' near the top of the script and put a more detailed note there, like say, "If you get an error here, you need to run this script with Python 3.6+." I mean, if you were to add some code above this line that also doesn't run in Python 2, then your comment wouldn't show up anymore. Moving it to the top avoids that.Imprest

© 2022 - 2024 — McMap. All rights reserved.