What does sys.version_info.major do?
I understand that sys.version_info returns the version of interpreter we are using. What role does major have to do in this?
How does it work in the following code?
import sys
if sys.version_info.major < 3:
#code here
else:
#code here
Python 3.5.1 (v3.5.1:37a07cee5969, Dec 5 2015, 21:12:44)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.version_info
sys.version_info(major=3, minor=5, micro=1, releaselevel='final', serial=0)
major can tell you whether it's python2 or python3. I guess it imports different libraries depends on the specific python versions.
I am using python 3.5.1, you can see the version_info about it.
Here's a trite example:
from __future__ import print_function
import sys
if sys.version_info.major<3:
input = raw_input # Python2 ~== eval(input())
else:
#code here
This makes Python 2.x behave a bit more like Python 3 ... the future import cannot be in the if suite because it must appear before other imports. But the changes in semantics for the input() builtin function between Python 2.x and Python 3 can handled in a conditional.
For the most part it's a bad idea to go much beyond this in your efforts to support Python2 and Python3 in the same file.
The more challenging changes between Python2 and Python3 relate to strings as bytes vs. the newer strings as Unicode; and thus the need to explicitly specify encodings and use bytes objects for many networking protocols and APIs.
For example, I have Python 3.5.3 installed on my computer. sys_version stores the following information:
sys.version_info(major=3, minor=5, micro=3, releaselevel='final', serial=0)
The reason version is split into major, minor and micro is that programmers writing code for multiple versions of Python may need to differentiate between them somehow. Most differences are between major versions 2 and 3 of Python and that explains the context of major usage in your code.
Related
I am trying to use a code which was written for python 2 and may run with python 3.6.0, but it does not run with python 3.6.4. It imports the IN module, and uses IN.IP_RECVERR. I tried to google it, but it is a 'bit' hard to find anything about a module called IN (naming fail?). To demonstrate in REPL, that it works in python 2, but not in 3.6.4:
$ python2
Python 2.7.14 (default, Jan 5 2018, 10:41:29)
[GCC 7.2.1 20171224] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import IN
>>> IN.IP_RECVERR
11
>>>
$ python3
Python 3.6.4 (default, Jan 5 2018, 02:35:40)
[GCC 7.2.1 20171224] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import IN
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'IN'
>>>
What is the replacement for this IN module in newer versions of python 3?
This is presumably the private plat-linux/IN.py module, which was never intended to be used. There have been plans to remove these plat-* files for a few zillion years, but it looks like it finally happened in issue 28027 for 3.6. As mentioned in What's New in Python 3.6:
The undocumented IN, CDROM, DLFCN, TYPES, CDIO, and STROPTS modules have been removed. They had been available in the platform specific Lib/plat-*/ directories, but were chronically out of date, inconsistently available across platforms, and unmaintained. The script that created these modules is still available in the source distribution at Tools/scripts/h2py.py.
Most of the useful constants that are at least somewhat portable (as in you can expect them to be available and work the same on your old laptop's linux and your brand-new Galaxy's linux, if not on OS X or Solaris) have long been made available through other places in the stdlib.
I think this specific one you're looking for is an example of not completely useless, but not portable enough to put anywhere safe, because linux documents the existence of IP_RECVERR, but not its value. So, you really need the version from your own system's ip headers.
The way to do this safely, if you actually need the IN module, is to run Tools/scripts/h2py.py with the Python version you're using, on the specific platform you need. That will generate an IN.py from the appropriate headers on your system (or on your cross-compilation target), which you can then use on that system. If you want to distribute your code, you'd probably need to put a step to do that into the setup.py, so it'll be run at install time (and at wheel-building time for people who install pre-built wheels, but you may need to be careful to make sure the targets are specific enough).
If you don't need to be particularly portable, you just need to access the one value in a few scripts that you're only deploying on your laptop or your company's set of identical containers or the like, you may be better off hardcoding the values (with a nice scare comment explaining the details).
In Python 2.7, how can I make the IDLE app use \__future__ division without typing from \__future__ import division manually every time I start IDLE?
If I put from \__future__ import division at the top of my .idlestartup file it is ignored, even though the other things in .idlestartup get executed. For example:
~> cat >.idlestartup
from __future__ import division
print("Executing .idlestartup")
~> idle -s
Here's what my IDLE window looks like after I try dividing:
Python 2.7.8 |Anaconda 2.1.0 (x86_64)| (default, Aug 21 2014, 15:21:46)
[GCC 4.2.1 (Apple Inc. build 5577)] on darwin
Type "copyright", "credits" or "license()" for more information.
>>>
Executing .idlestartup
>>> 2/3
0
>>>
I am using Mac OS X 10.9.5 Mavericks (also had the same problem on earlier versions of OS X). Note that the command line version above was included to make it easier to show what I'm talking about, but the version I'm more interested in is running the IDLE app from the GUI.
The solution suggested by Ashwini Chaudhary below worked for running the Anaconda version from the command line but not for running the IDLE app.
I was finally able to get future division working automatically in the IDLE app by adding "sys.argv.insert(1, '-Qnew')" to /Applications/IDLE.app/Contents/MacOS/IDLE. Both that and Ashwini Chaudhary's solution below seem brittle. I wonder if there is a cleaner way.
Adding the __future__ statement at the top of /usr/lib/python2.7/idlelib/PyShell.py did the job for me.
I am on Ubuntu, the path may vary for other OS:
>>> import idlelib
>>> idlelib.PyShell.__file__
'/usr/lib/python2.7/idlelib/PyShell.py'
Below is a simple test. repr seems to work fine. yet len and x for x in doesn't seem to divide the unicode text correctly in Python 2.6 and 2.7:
In [1]: u"爨爵"
Out[1]: u'\U0002f920\U0002f921'
In [2]: [x for x in u"爨爵"]
Out[2]: [u'\ud87e', u'\udd20', u'\ud87e', u'\udd21']
Good news is Python 3.3 does the right thing ™.
Is there any hope for Python 2.x series?
Yes, provided you compiled your Python with wide-unicode support.
By default, Python is built with narrow unicode support only. Enable wide support with:
./configure --enable-unicode=ucs4
You can verify what configuration was used by testing sys.maxunicode:
import sys
if sys.maxunicode == 0x10FFFF:
print 'Python built with UCS4 (wide unicode) support'
else:
print 'Python built with UCS2 (narrow unicode) support'
A wide build will use UCS4 characters for all unicode values, doubling memory usage for these. Python 3.3 switched to variable width values; only enough bytes are used to represent all characters in the current value.
Quick demo showing that a wide build handles your sample Unicode string correctly:
$ python2.6
Python 2.6.6 (r266:84292, Dec 27 2010, 00:02:40)
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.maxunicode
1114111
>>> [x for x in u'\U0002f920\U0002f921']
[u'\U0002f920', u'\U0002f921']
In python 2.7, by using
from __future__ import division, print_function
I can now have print(1/2) showing 0.5.
However is it possible to have this automatically imported at python startup ?
I tried to use the sitecustomize.py special module but the inport is only valid inside the module and not in the shell.
As I'm sure people will ask why I need that : teaching Python to teenagers I noticed that the integer division was not easy for them so we decided to switch to Python 3. However one of the requirement of the course was to be able to plot function and Matplotlib is pretty good but only valid for Python 2.7.
So my idea was to use a custom 2.7 installation...not perfect but I don't have a better idea to have both Matplotlib and the new "natural" division "1/2=0.5".
Any advice or maybe a Matplotlib alternative that is working on python 3.2 ?
matplotlib on python 3 is closer than you may think: https://github.com/matplotlib/matplotlib-py3; http://www.lfd.uci.edu/~gohlke/pythonlibs/#matplotlib.
Why not use PYTHONSTARTUP instead of sitecustomize.py?
localhost-2:~ $ cat startup.py
from __future__ import print_function
from __future__ import division
localhost-2:~ $ export PYTHONSTARTUP=""
localhost-2:~ $ python
Python 2.7.2 (v2.7.2:8527427914a2, Jun 11 2011, 15:22:34)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 1/2
0
>>> print("fred",end=",")
File "<stdin>", line 1
print("fred",end=",")
^
SyntaxError: invalid syntax
>>> ^D
localhost-2:~ $ export PYTHONSTARTUP=startup.py
localhost-2:~ $ python
Python 2.7.2 (v2.7.2:8527427914a2, Jun 11 2011, 15:22:34)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 1/2
0.5
>>> print("fred",end=",")
fred,>>>
No need to compile a new version of Python 2.x. You can do this at start up.
As you found, sitecustomize.py does not work. This is because the from __future__ import IDENTIFIER isn't an import. It flags the module to be compiled under special rules. Any module that uses those features must have the __future__ import, as well as the interactive console.
The following shell command will start the interactive console with division and print_function active:
python -ic "from __future__ import division, print_function"
You could alias to python (on linux) or set up a launcher to hide the extra stuff.
If you are using IDLE, the PYTHONSTARTUP script #DSM suggests should work there as well.
Note that these are not global throughout the interpreter, it only affects the interactive console. Modules on the file-system must import from __future__ explicitly to use the feature. If this is an issue, I suggest making a template to base work off of with all the needed imports:
# True division
from __future__ import division
# Modules
import matplotlib
# ... code ...
def main():
pass
if __name__ == "__main__":
main()
This may not be practical, but you may be able to compile a custom Python with the Python 3 division behavior backported. The problem with this is matplotlib might require the Python 2 behavior (although I'm not sure).
I'd like to use with statement in Python 2.5 in some production code. It was backported, should I expect any problems (e.g. with availability/compatibility on other machines/etc)?
Is this code
from __future__ import with_statement
compatible with Python 2.6?
Yes, that statement is a no-operation in Python 2.6, so you can freely use it to make with a keyword in your 2.5 code as well, without affecting your code's operation in 2.6. This is in fact the general design intention of "importing from the future" in Python!
You can call this in Python 2.6 and 3.0/1 without problems (it's a no-op there).
with_statement wasn't back ported but implemented in Python 2.5. Adding new keywords or syntax can break existing applications. With Python the way they decided to handle this is allow people to opt-in to those features early so you can slowly transition your code over.
From http://python.org/doc/2.5.2/ref/future.html
A future statement is a directive to
the compiler that a particular module
should be compiled using syntax or
semantics that will be available in a
specified future release of Python.
The future statement is intended to
ease migration to future versions of
Python that introduce incompatible
changes to the language. It allows use
of the new features on a per-module
basis before the release in which the
feature becomes standard.
You can actually inspect futures to get information on when first supported, when the import isn't needed anymore, etc.
Python 2.5.1 (r251:54863, Apr 18 2007, 08:51:08) [MSC v.1310 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import __future__
>>> dir(__future__)
['CO_FUTURE_ABSOLUTE_IMPORT', 'CO_FUTURE_DIVISION', 'CO_FUTURE_WITH_STATEMENT', 'CO_GENERATOR_ALLOWED', 'CO_NESTED', '_Feature', '__all__', '__builtins__',
__doc__', '__file__', '__name__', 'absolute_import', 'all_feature_names', 'division', 'generators', 'nested_scopes', 'with_statement']
>>> __future__.with_statement
_Feature((2, 5, 0, 'alpha', 1), (2, 6, 0, 'alpha', 0), 32768)
>>>
I personally have been heavily using the with_statement in Python 2.5 for well over a year and have not had issues. I also transparently run that code with Python 2.6. There are some weird corner cases they have worked at cleaning up in the language, mostly related to cleanly and correctly compacting nested with statements.