1

I tried to see if this is a duplicate, but was unable to find exactly this question. I'm also pretty ignorant regarding this stuff.

I am using Python 3.7.2 (the only version of python on my windows 10 computer) and have created a virtual environment using venv:

python -m venv /path/to/new/virtual/environment

I added some packages via pip install and created a requirements.txt file via pip freeze. I wrote some code using packages from the virtual environment.

I would like to share my code with colleagues. I can give them the code and the requirements file, but requirements.txt doesn't specify which version of python I used (3.7.2). What is the appropriate mechanism to communicate this information to my colleagues? Can the requirements.txt file be amended to include the fact that I used 3.7.2 and that anyone running my code should also use 3.7.2? Would the answer to this question depend on whether I or my colleagues have multiple version of python installed on our computers?

rhz
  • 960
  • 14
  • 29
  • You would use a `setup.py` for that. But in general you should make your code a compatible with different Python versions as possible. – Klaus D. Jun 19 '19 at 01:53
  • @KlausD. kinda disagree. There's a lot of interesting features in 3.7 which I find compelling enough a reason to break backwards compatibility. Unless you want to publish a library to many clients I don't see a lot of purpose. @ rhz I find [tox](https://tox.readthedocs.io/en/latest/) a really good tool for solving this problem. It handles specifying python versions, creates virtual environments for you and many more great features. Here's a good starting point https://github.com/ferencberes/tox-example – flakes Jun 19 '19 at 02:25
  • Another note for tox, if you want to support multiple versions you can set it up so tests run automatically on all of the major/minor versions you wish to target. – flakes Jun 19 '19 at 02:31

2 Answers2

0

Typically, your script should require users to install an older version of Python. Python very rarely breaks backward compatibility (like when going from 2.x to 3.x), so there really is no need to specify a specific version of 3.x

Of course, it's possible that the version your colleagues have is too old, in which case they should upgrade. Your script can simply check whether a sufficiently new version of Python is available itself:

import sys

if sys.version_info.major < 3 or sys.version_info.minor < 5:
    print("Python version 3.5 or newer required.")
    exit(1)

Just ensure that you know why you need a specific version. If your colleagues have a sufficiently up to date version installed and they install the packages from the requirements.txt, the package manager will automatically install the version of the packages appropriate to their current version of Python and, assuming these are well-maintained packages, they should also be backwards compatible. If not, you can specify specific versions of the packages in the requirements.txt.

If what you're sharing is itself a package, you can do this in the setup.py, more here Prevent package from being installed on old Python versions

Note that if you want the above to continue working beyond 3.x (because the minor version of 4.0 will be 0, which is < 5), you might want to use:

if sys.version_info < (3, 5):
    etc.

But this assumes 4.x will be backwards compatible for everything you're doing as well - depending on what you're looking to do specifically, you may want to make an exception for future versions as well.

Grismar
  • 27,561
  • 4
  • 31
  • 54
  • I wouldn't say its very rare with Python to break the backwards compat, but they at least attempt not to. There's still plenty of projects still behind the breaking `async` keyword changes in Python 3 minor version changes. I will not be surprised if Python 4 adds more headache to this problem. – flakes Jun 19 '19 at 02:30
  • 1
    Your version test is broken; when Python 4.0 comes out, it will fail due to the `minor` version being less than `5`. Lexicographic ordering is hard; just let the `tuple` comparator do it for you: `if sys.version_info < (3, 5):` is correct and more concise (and works on version 2.6/3.0 and earlier, before `version_info` became a named tuple). If you're really paranoid about them reordering `sys.version_info` or want the full names, `if (sys.version_info.major, sys.version_info.minor) < (3, 5):` also works (unless you're on 2.6/3.0 or earlier). – ShadowRanger Jun 19 '19 at 02:59
  • It's a good point @ShadowRanger, although at that point, there might be backwards compatibility breaking changes that should cause the script to fail as well, so a check and possibly a change would be required. – Grismar Jun 19 '19 at 03:17
  • @Grismar: Yes, if you want to be careful to avoid claiming to support 4.0, you'd write it as `if not (3, 5) <= sys.version_info < (4, 0):`. Using your original test would fail on 4.0, and suddenly work on 4.5, so it's not the way to go no matter what you plan to do for 4.x. – ShadowRanger Jun 19 '19 at 03:24
  • You mean I should develop using an older version generally (and not that if I, for example, develop in 3.7.2 then I should require users to run with at least, say 3.6.0), right? I use pandas which has big changes from version to version, so I need to include its version in requirements.txt. Not sure if a newer version of pandas requires a newer version of python. In summary, if I develop in python 3.7.2 and pandas 24.2, then I should specify the version of pandas and use your sys.version_info tests to ensure than major is not < 3 and minor is not less than 7. Do I have to test for micro? – rhz Jun 19 '19 at 03:58
  • 1
    @rhz: In theory, Python uses (mostly) semantic versioning, so no significant changes are supposed to be introduced between micro releases, let alone breaking changes. It's not perfect (Python 2.7, being the final Python release, has made some breaking changes intentionally, e.g. in 2.7.9 they significantly refactored the `ssl` module to improve SSL security and make it easier to write code that targeted both 2.7.9+ and 3.4+; other micro releases [have accidentally broken compatibility](https://bugs.python.org/issue29943)), but most of the time, you're safe. – ShadowRanger Jun 20 '19 at 22:46
0

Venv with different version of python is more important when you have a system with multiple versions of python. For example, CentOS 7 EPEL comes with python 2.7 and python 3.4 installed. When you attempt to find a more recent version, you can't find it in the official repositories. That is because the long term support model pin certain embedded tools to a specific version and only provide support for bug fixes. 3.4.1 could be the intial version, but updates are available for 3.4.2 and 3.4.3. So how do you use 3.5 or 3.6 or 3.7? You build it from source and install it in an alternative location (/usr/local/bin or /usr/opt/bin).

This where Venv really shines.

From a regular prompt, python3 will invoke python3.4 and python will invoke 2.7.

But you can use the python of your choice for development.

Example: You install python3.7 in the alt location. System python is unchanged and all system utilities work as they should.

/usr/local/bin/python3.7 -m venv mypython_dir creates a new virtual environment.

source mypython_dir/bin/activate will activate the that environment

From that point on python is python3.7 and pip is pip3.7 from the /usr/local/bin directory that was copied into the venv directory.

On windows this is less of an issue since python is not embedded at the system level. You'll see a lot of question for linux systems where people have forced an upgrade to system python on a LTS version. Bad things happen. If you want or need a specific version to run your module then Grismar's answer above is what you want to do.

WombatPM
  • 2,561
  • 2
  • 22
  • 22