can one python script run both with python 2.x and python 3.x
Many scripts can run on both 2.x and 3.x. (I've got a bunch I work on on a daily basis, and I've converted various open source libraries from 2.x-only to dual-version.)
A few things make it much easier:
- Require 2.7, or at least 2.6+, for 2.x users. Otherwise, for example, you cannot raise and exceptions with parameters or catch them into variables, and other such severe limitations.
- Require 3.3+, or at least 3.2+, for 3.x users. Most of the gratuitous incompatibilities (like the
u
prefix being taken away) were reversed in 3.2 or 3.3. - Use the six library.
- Use
__future__
statements. - Always be clear in your head about whether you mean
bytes
(always 8-bit),unicode
(must encode if you want 8-bit), orstr
(whatever most of the stdlib APIs expect), andencode
anddecode
as necessary. - Regularly run
2to3
on your code. (But don't blindly do everything it says. If, e.g., you're usingd.keys()
ormap(f, l)
because you don't care whether you get back alist
or not, you'll get a warning, because2to3
doesn't know you don't care.)
Alternatively, instead of trying to write code that runs on both, write code that runs on 2.x, but can be automatically transformed by 2to3
into running 3.x code, and make that part of your installation process (in setup.py
, if sys.version_info >= (3, 0):
do the 2to3
step).
From your edit, it sounds like you're mostly concerned with what to put in the #! line. For that:
/usr/bin/env python
This isn't guaranteed to work—but then env
isn't guaranteed to work in the first-place… You can count on the fact that:
- On just about any system where the platform/distro supplies only 2.x,
python
is Python 2. - On just about any system where the platform/distro supplies both,
python
is Python 2. - On just about any system where the platform/distro supplies only 3.x (which currently is very rare, but will presumably eventually be more common),
python
is Python 3.
However:
- On a system where the platform supplies neither, if the admin only installed 3.x, it will likely (as of early 2013) not be available as
python
. There's not much you can do about this one.
If the last one is a serious problem, you can work around it by adding a launcher script, written in sh, that tries python
and then tries python3
if that fails.
The nice way to do this is to specify the launcher script itself as the shebang interpreter in your Python script. Linux can handle this, but it's configurable, and at least some distros disable it by default—and most other *nix systems can't do it.
If that doesn't work, the next best option is to make the user run the launcher script—that is, tell them to do ./check.sh
instead of ./check.py
, and check.sh
figures out the right Python interpreter and runs $python ./check.py
for the user.
If you want to get really tricky, you could even embed the Python script as a heredoc inside the shell script, so you only need to distribute one file. They run ./check.sh
, and it finds the right Python and runs it on the heredoc.