Perl's BEGIN{} block in Python - python

I have Python code that uses the "with" keyword (new in 2.6) and I want to check if the interpreter version is at least 2.6, so I use this code:
import sys
if sys.version < '2.6':
raise Exception( "python 2.6 required" )
However, the 2.4 interpreter chokes on the with keyword (later in the script) because it doesn't recognize the syntax, and it does this before it evaluates my check.
Is there something in Python analogous to Perl's BEGIN{} block?

Take a look here:
How can I check for Python version in a program that uses new language features?

Perhaps someone has a better answer, but my first thought would be to have a separate script to perform the check, then import the "real" script once the check has passed. Python won't check the syntax until the import happens.
import sys
if sys.version < '2.6':
raise Exception( "python 2.6 required" )
import myscript # runs myscript

Related

flake8 conditional with python version in stub file

I need to support both python 3.8 and versions lower that 3.8, but the package I need to import into my stub (*.pyi) file had different name in <3.8
import sys
if sys.version_info.minor < 8:
import xyz
else:
import zyx
In general this should do the job, but when I run flake8 with *.pyi files config (flake8 --config flake8-pyi.ini) I get this:
Y002 If test must be a simple comparison against sys.platform or sys.version_info
Any ideas what could be done about that?
Thanks in advance!
From the description of flake8-pyi (a flake8 plugin, not part of flake8 itself):
Y002: If test must be a simple comparison against sys.platform or sys.version_info. Stub files support simple conditionals to indicate differences between Python versions or platforms, but type checkers only understand a limited subset of Python syntax, and this warning triggers on conditionals that type checkers will probably not understand.
The fix is to change your condition to:
if sys.version_info < (3, 8):
note that your code would break for 2.8 (yes, some people do this!) and 4.0 so you should be careful with eliding parts of comparisons ;) -- I've written a flake8 plugin which helps lint against conditions that might be problematic: flake8-2020

Dynamically choosing Python library based on Python version

I am writing a Python script which needs to run on RHEL 6.x which defaults to Python 2.6 but also should work with the latest Python. I need to parse command-line arguments, however Python 2.6 only includes optparse which in recent Python has been deprecated in favor of argparse. Is there a way to dynamically select whether to use argparse or opt parse (I realize it would require two parsing algorithms)?
Try to import argparse first and then use optparse if it can't be found:
try:
import argparse
# Argparse-specific stuff
except ImportError:
import optparse
# Optparse-specific stuff
You can also check the python version using sys.version or sys.version_info.
import sys
if (sys.version_info.major >= 2 and sys.version_info.minor >= 7):
import argparse
# ...
else:
import optparse
Or, you could just use optparse on all versions, if you do not need the improved features argparse has
Stick with optparse for now, or install argparse from PyPI for the Python 2.6 installation.
Don't try to support both just to support two Python versions; save yourself the headache. optparse may be deprecated but still works just fine when run with Python 2.7. It just has fewer features than argparse can offer.
If you have to run on Python 3.x installations too, then you could try to support both with an import guard:
try:
import argparse
# configure argparse
except ImportError:
import optparse
# configure optparse
but it'd be much easier to just ship with argparse as a dependency.

Python: How can I create a Python project compatible to Python 2 and Python 3?

I want to create a package which should be compatible to Python 2.7 and Python 3.3.
The logic should exist only once.
How do you normally represent the programming logic - in Python 2.7 or Python 3.3?
Or do you choose a different way?
EDIT: How this issue is handled in the core?
You do it by quite simply only using those bits of the language that is the same, and by having conditions or exception handling during other parts.
This is harder or easier depending on what your software do, and what versions of Python you need to support. By supporting just Python 2.6, 2.7 and 3.3 it becomes relatively simple.
Exactly how you do it is not answerable in a question on SO, because there is a lot to it.
I recommend you check out this book: http://python3porting.com/ , especially the chapter "Supporting Python 2 and 3 without 2to3 conversion" and the Appendices, that has loads of examples of how to solve most incompatibilities.
The six library may also be useful.
I tend to use a number of __future__ imports (which are, presumably, safely ignored in Python 3), and the occasionaly try except for some import statements. In addition, I define a stringtype for basestring / str compatibility. Just depending on what I need per module.
For example:
from __future__ import absolute_import
from __future__ import unicode_literals
from __future__ import division
from __future__ import print_function
try:
import ConfigParser as cfgparser
except ImportError:
import configparser as cfgparser
try:
stringtype = basestring
except NameError:
stringtype = str
I think the six package already does this, so that may be another good option.

How to get Python 2.6 documentation of the future-imported print() function?

I use Python 2.6 with the new print() function:
from __future__ import print_function
Now, how can I get pydoc to print a documentation of that function? A simple
$ pydoc print
will print documentation about the 2.6 version of the print function.
(Needless to say, I can find the documentation online but I'd like to be able to access it using pydoc on the command line.)
Unfortunately there's no shortcut:
$ python -c 'from __future__ import print_function; help(print)'
This is probably not what you want, but on my system, I can do pydoc3.2 print as I have both python 2.6 and python 3.2 installed...

What to reference in the shebang python26 or python2.6

For a Python script I need a specific Python version. Now my installation of Python 2.6 contains both python26 and python2.6
Which one should I put in the shebang?
Option 1:
#!/usr/bin/env python2.6
Option 2:
#!/usr/bin/env python26
EDIT: Yes, there is a reason not to use plain python. In some of our environments in the university python is linked to python2.4 and my code uses quite some 2.6 features.
You can't always guarantee that the shebang will be used (or even that the user will have that version).
You shouldn't really limit to a specific version exactly. It's best to require at least a given version (if your code works on Python 2.6, why wouldn't it work on Python 2.7? I might not have Python 2.6 installed in a few months time.)
I would stick with the /usr/bin/env python shebang and instead dynamically detect the version. Believe it or not, the "normal" way of doing this is:
import sys
ver = sys.version[:3]
That will give you a 3-character string such as "2.6" or "2.7". I would just check that the first character = '2' (assuming you want to prevent Python 3 from running your scripts, since it's largely incompatible) and the third character >= '6'.
Edit: See Petr's comment -- use sys.version_info[0:2] instead (gives you a pair like (2, 6) or (2, 7).
Just checked on my Linux system there is only python2.6 not python26 so the former looks better.
Just to clarify, I would use conditional imports instead, in my case I need OrderedDict which is python 2.7+ only;
try:
from collections import OrderedDict
except ImportError:
print("Python 2.7+ is needed for this script.")
sys.exit(1)
Why don't you just use /usr/bin/python instead? Is there any reason for not doing that?
If you don't have it already, you can create a link to it using this command:
ln -s /usr/bin/python26 /usr/bin/python
This ensures compatibility if you ever upgrade your python in the future.

Categories