How do you use a python2 module inside a python3 program - python

I've written a 40k line program in python3. Now I need to use a module throughout my program that is called pytan which will impart a functionality addition. The problem is that pytan is written in python2.
So is it possible to switch the interpreter to python 2.7 inside one script that is called by another running in python 3?
What's the best way to handle this situation.

You cannot "switch the interpreter to python 2.7". You're either using one or the other. Your choices are effectively:
Come up with an alternative that doesn't require the pytan module.
Modify the pytan module so that it runs under Python 3.
Modify your code so that it runs under Python 2.
Isolate the code that requires pytan such that you can run it as a subprocess under the python 2 interpreter. There are a number of problems with this solution:
It requires people to have two versions of Python installed.
It will complicate things like syntax highlighting in your editor.
It will complicate testing.
It may require some form of IPC (pipes, sockets, files, etc...) between your main code and your python 2 subprocess (this isn't terrible, but it's a chunk of additional complexity that wouldn't be necessary if you could make one of the other options work).

Related

Can I pre-compile a python script?

I have a python script. Lets say http://domain.com/hello.py, which only prints "Hello, World!".
Is it possible to precompile this Python file?
I get around 300 requests per second and the overhead of compiling is way to high. In Java the server can handle this easily but for calculations Python works much easier.
the problem is not that you need to "precompile" python, the problem is that you are trying to execute python scripts using normal cgi script stuff...
the real answer is to use a better web backend than simple cgi to run your python
I would suggest the following in order of appearance
1. nginx + gnunicorn
2. apache2 + mod-wsgi
3. something else
4. anything else
...
n-1. fcgi
n. cgi
I know this isnt really an answer and is entirely opinion based
Python code is compiled automatically the first time it is run, by the CPython (standard Python) interpreter. You can pre-compile it if you want to optimize the first request, but that usually isn't necessary. Aside from that, you'd need to convert your Python code into a Python C / cython Module. There are some tools to help you convert Python code into a Python Module if that's the route you want to go.
There's also a Python module called SciPy that's commonly used for Scientific Computing and Data Science applications, which provides a tool called Weave which allows you to inline C/C++ code into your Python code allowing certain performance-critical portions of the code to run using compiled C/C++ code.
via the python interface where your python source file is abc.py:
import py_compile
py_compile.compile('abc.py')

Interface Jython script from Python3 module?

If I have a script, or in this case just a function or two, written in Jython -- is there a way to interact with that code from my Python3 project?
No, not until Jython catches up with CPython enough for your whole Python 3 project to run in Jython. You can't run part of a Python application with one interpreter and the rest with another. You might be able to juggle multiple processes using remote procedure calls using pickle, but it'll be complex and brittle, not to mention slow (has to copy all data involved). If it's pure Python, just port those two functions to Python 3 (likely easy), or port your project to Python 2.5 (probably much harder). If it uses Jython's JVM interop, there are alternatives working with CPython, though possibly less mature. Depending on what you need Java for, there might be a pure Python alternative.

can one python script run both with python 2.x and python 3.x

i have thousands of servers(linux), some only has python 2.x and some only has python 3.x, i want to write one script check.py can run on all servers just as $./check.py without use $python check.py or $python3 check.py, is there any way to do this?
my question is how the script check.py find the Interpreter no matter the Interpreter is python2.x and python3.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), or str (whatever most of the stdlib APIs expect), and encode and decode as necessary.
Regularly run 2to3 on your code. (But don't blindly do everything it says. If, e.g., you're using d.keys() or map(f, l) because you don't care whether you get back a list or not, you'll get a warning, because 2to3 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.
Considering that Python 3.x is not entirely backwards compatible with Python 2.x, you would have to ensure that the script was compatible with both versions. This can be done with some help from the 2to3 tool, but may ultimately mean running two distinct Python scripts.
In the general case, no; many Python 2 scripts will not run on Python 3, and vice versa. They are two different languages.
Having said that, if you are careful, you can write a script which will run correctly under both. Some authors take extra care to make sure their scripts will be compatible across both versions, commonly using additional tools like the six library (the name is a pun; you can get to "six" by multiplying "two by three" or "three by two").
However, it is now 2020, and Python 2 is officially dead. Many maintainers who previously strove to maintain Python 2 compatibility while it was still supported will now be relieved and often outright happy to pull the plug on it going forward.

What is the best method to call a Python 3.x program from within Python 2.x?

I'm writing a Django web application. As of now, Django does not support Python 3. For the purposes of my web application, and without getting into to much detail, I essentially need to use some libraries that only support Python 3. Suffice it to say that after much thorough research no 2.x alternative was found.
So my question is this: How should I go about this?
I have both Python 2 and 3 installed on my server, and I have the Python 3 code written and waiting to be called. I was considering simply using the subprocess module, effectively calling Python 3 from the command line, but the question is, is this the best method or is there a best practice I could use instead here? Using subprocess seems pretty hackish to me. Don't get me wrong, I'm okay with hackish, I just want to make sure there's nothing else I should be doing instead.
Since the Python 3 and Python 2 interpreters are totally separate executables and have separate libraries installed on your system, using subprocess to invoke one from the other is the best practice. It's not a hack at all. There are a number of ways to pass data between them but the two interpreters should be run as separate processes.
That said, you may need to keep in mind the startup time associated with launching an interpreter process. That gets back to how to pass data between the two processes. If your Python 2 code is going to be frequently calling the Python 3 routines, you may need to structure the Python 3 program as a daemon. But you would still use subprocess to launch it.
Run the 3.x program as a separate service and then connect using some kind of RPC mechanism?

Is there a standard way to make sure a python script will be interpreted by python2 and not python3?

Is there a standard way to make sure a python script will be interpreted by python2 and not python3? On my distro, I can use #!/usr/bin/env python2 as the shebang, but it seems not all distros ship "python2". I could explicitly call a specific version (eg. 2.6) of python, but that would rule out people who don't have that version.
It seems to me that this is going to be increasingly a problem when distros will start putting python3 as the default python interpreter.
http://docs.python.org/library/sys.html#sys.version_info
using the sys module you can determine the version of python that is running and raise an exception or exit or whatever you like.
UPDATE:
You could use this to call the appropriate interpreter. For example, set up a small script that does the checking for you, and use it in the shbang. It would check the python version running, and if not what you want, looks for one you want. Then it would run the script in that version of python (or fail if nothing good was found).
This is a bit of a messy issue during what will be a very long transition time period. Unfortunately, there is no fool-proof, cross-platform way to guarantee which Python version is being invoked, other than to have the Python script itself check once started. Many, if not most, distributions that ship Python 3 are ensuring the generic python command is aliased by default to the most recent Python 2 version while python3 is aliased to the most recent Python 3. Those distributions that don't should be encouraged to do so. But there is no guarantee that a user won't override that. I think the best practice available for the foreseeable future is to for packagers, distributors, and users to assume python refers to Python 2 and, where necessary, build a run-time check into the script.
Using sys.version_info you can do a simple value test against it. For example if you only want to support version 2.6 or lower:
import sys
if sys.version_info > (2,6):
sys.exit("Sorry, only we only support up to Python 2.6!")
Not quite the same situation, but the company I work for has an app that can run Python scripts (among its many features). After numerous support issues involving Python installations on various platforms, we decided to just install our own Python interpreter with the app. That way we know exactly where it is installed and what version it is. This approach may be too heavyweight for your needs (the Python package is only about 10% of our app's bits) but it definitely works.
Depends on how you're distributing it, I guess.
If you're using a normal setup.py file to manage your distribution, have it bomb out if the user is trying to install it in Python 3.
Once it's installed, the shebang of the console script created by (say) setuptools will likely be linked to the specific interpreter used to install it.
If you're doing something weird for your installation, you can in whatever installation script you're using look for python interpreters and store a choice. You might first check whether whatever is called "python" is a 2.x. If not, check for "python2.7", "python2.6", etc to see what's available.
As I understand different distros will be in different locations in your drive. Here are some suggestions that come to mind -
You could use UNIX alias to create shortcuts pointing to the different distros. Eg: alias py2="/usr/bin/python2.X". So when you run your script you could use py2 xx.py
Or other way could be to modify your PYTHON_PATH environment variable.
Or if I am not wrong there is a provision in sys module to get the current python version number. You could get that & deal appropriately.
This should do it...
You can use the autotools to pick a Python 2 interpreter. Here is how to do that. Guaranteeing a correct shebang may be tricky to do elegantly; here is one way to do that. It may be easier to simply have a light Bash wrapper script, wrapper.sh.in that looks something like:
#!/bin/bash
PYTHON2="#PYTHON#" #That first link enables this autotool variable
"$PYTHON2" "$#" #Call the desired Python 2 script with its arguments
Call wrapper.sh (after a ./configure) like:
./wrapper.sh my_python2_script.py --an_option an_argument
I believe this will do what you want, namely test for a non-specific version of Python less than 3.x (as long as it doesn't contain a from __future__ import print_function statement).
try:
py3 = eval('print')
except SyntaxError:
py3 = False
if py3: exit('requires Python 2')
...
It works by testing to see if print is a built-in function as opposed to a statement, as it is in Python3. When it's not a function, the eval() function will raise an exception, meaning the code is running on a pre-Python 3.0 interpreter with the caveat mentioned above.

Categories

Resources