This question already has answers here:
Can Syntax Errors be handled?
(2 answers)
Syntax error on print with Python 3 [duplicate]
(3 answers)
Closed 9 years ago.
I'm trying to write a block of code at the top of my programs that, if the program is accidentally run in Python 2.x, it will give an error message and quit, but if run in Python 3.x will run normally:
try:
print "Error: This program should only be run in Python 3."
raw_input('>')
exit()
except SyntaxError:
pass
print("I see you're running Python 3.")
# rest of program
This works correctly in Python 2.7 (i.e., it displays the error and quits), but when I run it in Python 3.3, I get a SyntaxError, even though I told it to have an exception.
File "version.py", line 2
print "This program should only be run in Python 3"
^
SyntaxError: invalid syntax
What am I missing?
SyntaxErrors are thrown at compile-time. You cannot catch them like runtime exceptions.
If you want to check python version, look at sys.version_info.
i.e.
import sys
if sys.version_info.major < 3:
sys.exit('This program should only be run in Python 3')
Here's a small example on how to do what you want:
import sys
if sys.version_info.major == 2:
print("Error: This program should only be run in Python 3.")
raw_input('>')
exit(0)
This code will run in python2 and python3. You don't need to use a try catch in that case. Since in python2, it happens that the ( and ) will have no effect since they aren't tuples. You can write that kind of thing and it will work in python2 and python3 without SyntaxError.
Related
This question already has answers here:
Python 3 print without parenthesis
(10 answers)
Closed 4 years ago.
So I started learning python 3 and I wanted to run a very simple code on ubuntu:
print type("Hello World")
^
SyntaxError: invalid syntax
When I tried to compile that with command python3 hello.py in terminal it gave me the error above, but when used python hello.py (I think it means to use python 2 instead of 3) then it's all fine. Same when using python 3 and 2 shells in the terminal.
It seems like I'm missing something really stupid because I did some research and found no one with the same issue.
In Python3, print was changed from a statement to a function (with brackets):
i.e.
# In Python 2.x
print type("Hello World")
# In Python 3.x
print(type("Hello World"))
In Python 3.x print() is a function, while in 2.x it was a statement. The correct syntax in Python 3 would be:
print(type("Hello World"))
This is because from Python 3, print is a function, not a statement anymore. Therefore, Python 3 only accepts:
print(type("Hello World"))
I have the following code which runs fine on python 2 but throws error on python 3
import sys
if sys.version_info > (3,):
#print("Python 3")
#Try Block
except urllib2.HTTPError as err:
else:
#print "Python 2" # Throws error on python 3
#Try Block
except urllib2.HTTPError, err: # Throws error on python 3.
The above code returns "Python 2" in python 2, but throws syntax error on python 3 (For python 2 syntax ).
Can anyone tell me why is this happening ? And what is the work around to fix those syntax errors in python 3 ?
Note : I am aware of print syntax on Python 3
Thanks you!
The problem is that the parser runs before any code is evaluated at runtime. Your check sys.version_info > (3,) runs at run time, after the code was already parsed and compiled. So doing such checks, you are able to make changes at runtime, but that does not help you when dealing with syntax changes.
The syntax is parsed and compiled before any code is interpreted, that is why you get syntax errors even for code that is never run at runtime.
If you are trying to create a polyglot script that is able to run on both Python 3 and Python 2, then you will need to make sure to use a syntax that works on both. For print in particular, you can import the print function in Python 2, so you can use it just like you would in Python 3:
from __future__ import print_function
Some newer features won’t work that way (for example everything async), but for the most part, you can make it work somehow.
If you end up depending on stuff with Python 3 that requires Python 2-incompatible syntax, then you could put that into a separate module and import that module conditionally at runtime. That way it won’t be loaded for Python 2, so the Python 2 parser wouldn’t attempt to load the incompatible syntax.
As for why Python 2 does not throw an error, that’s actually very simple: print('foo bar') is valid syntax in Python 2, even with the print statement. That is because you can put parentheses around anything without impacting the value. So what you actually do there is this:
print ('foo bar')
^^^^^
print statement
^^^^^^^^^^^
value, wrapped in parentheses (that don’t do anything)
That’s also the reason, why the following produces different results in Python 3 and 2:
print('foo', 'bar')
In Python 3, you get foo bar as the output, while Python 2 gives you ('foo', 'bar'). That is because the comma inside the parentheses now makes this a tuple, so you pass a tuple to the print statement. – Importing the print function fixes this to give you the same behavior on Python 2 as on Python 3.
Even though the line print "Python 2" will never be executed in Python 3, it will still be compiled to byte code (or at least attempted). That line is a syntax error in Python 3, which requires the printed items to be in parentheses. Look up the documentation for more details: other changes to print were also made.
So remove the error. Make the line
print("Python 2") # Throws error on python 3
instead. That way it works in both Python 2 and in 3. There are many sites that discuss how to write code that executes in both versions of Python. The parentheses are merely ignored in version 2 but are needed in version 3. This works if you print only one item: more than one gets more complicated.
There is another way to do printing in both versions, using from __future__ import print_function but the way I showed is easier.
Note that your attempted comment in the line is also not proper Python syntax. Change the // to # and it works.
This question already has answers here:
What does "SyntaxError: Missing parentheses in call to 'print'" mean in Python?
(11 answers)
Closed 6 years ago.
I am learning a tutorial for Python language and trying to write a basic "Hello World!" program.
But when I do all steps described in the book I receive an error.
>> print "Hello World!"
SyntaxError: Missing parentheses in call to 'print'
Why I am getting this error?
Is my book wrong?
it seems that you're using Python 3.x.
In python 3.x, the print statement is a function and you need to use it as a function like this
print("Hello World!")
Your book is right, but might be outdated a bit. It seems it describes Python version 2, but you try to run your example on the version 3.
Python 3 has changed some features and this one is the most annoying to switch from P2 to P3.
"print" statement changed to function rather than operator as was in P2.
Calling function you should always use parentheses.
So, if you want to run your program in Python3 you should call it:
print("Hello World!")
And that's it.
If you want to use examples from your book as is - install Python2 and it should work.
I would like to check if my interpreter is using Python 3, before parsing the entire file, to print a decent error message otherwise.
In this question, there is an answer regarding Python 2.4 / 2.5. However, when I tried to reproduce the solution in my Python 2.7 / 3.3 environment, it did not work.
For instance, running the following file:
try:
eval("print('', end='')")
except SyntaxError:
raise Exception("python 3 needed")
print("", end="")
Results in the following error:
File "test_version.py", line 6
print("", end="")
^
SyntaxError: invalid syntax
That is, eval is not evaluated soon enough to prevent the parser from reaching line 6.
Is there another hack that might work here?
The classic way to check for the version of Python that is running your script is to use the tuple returned by sys.version_info (http://docs.python.org/2/library/sys.html):
from __future__ import print_function
import sys
if sys.version_info[0] < 3:
print("This program needs Python version 3.2 or later")
sys.exit(1)
The reason to enable print() as a function through the import from __future__ is because the script wouldn't parse under Python 3.x if the print statement was used.
Move code using print() as a function to a separate module and make the main script do the testing only.
It doesn't matter where in the module the print() function call is made, it is a syntax error because you are not using print as a statement. You'd put that in a separate module imported after your test.
try:
eval("print('', end='')")
except SyntaxError:
raise Exception("python 3 needed")
import real_script_using_print_function
However, in Python 2 you can also add:
from __future__ import print_function
at the top to make print() work in Python 2 as well. It is perfectly feasible to write Python code that runs on both Python 2 and 3 if taken care.
I have a large piece of Python 2 only code. It want to check for Python 3 at the beginning, and exit if python3 is used. So I tried:
import sys
if sys.version_info >= (3,0):
print("Sorry, requires Python 2.x, not Python 3.x")
sys.exit(1)
print "Here comes a lot of pure Python 2.x stuff ..."
### a lot of python2 code, not just print statements follows
However, the exit does not happen. The output is:
$ python3 testing.py
File "testing.py", line 8
print "Here comes a lot of pure Python 2.x stuff ..."
^
SyntaxError: invalid syntax
So, it looks like python checks the whole code before executing anything, and hence the error.
Is there a nice way for python2 code to check for python3 being used, and if so print something friendly and then exit?
Python will byte-compile your source file before starting to execute it. The whole file must at least parse correctly, otherwise you will get a SyntaxError.
The easiest solution for your problem is to write a small wrapper that parses as both, Python 2.x and 3.x. Example:
import sys
if sys.version_info >= (3, 0):
sys.stdout.write("Sorry, requires Python 2.x, not Python 3.x\n")
sys.exit(1)
import the_real_thing
if __name__ == "__main__":
the_real_thing.main()
The statement import the_real_thing will only be executed after the if statement, so the code in this module is not required to parse as Python 3.x code.