Meysam
Meysam

Reputation: 18137

pytest running with another version of python

I've installed pyenv and have different versions of python installed with it:

$ pyenv versions
  system
  2.7.1
  3.2.5
  3.5.0
  3.5.1
* 3.5.2

I use the following command to switch to python 3.5.2:

pyenv shell 3.5.2

And when I check the python version this is what I get:

$ python --version
Python 3.5.2

But when I run pytest, it still runs under python 2.7.6:

pytest -v
==================================================================== test session starts ====================================================================
platform linux2 -- Python 2.7.6, pytest-3.0.3, py-1.4.31, pluggy-0.4.0 -- /usr/bin/python

Why is pytest running under the older version?

Upvotes: 50

Views: 51824

Answers (4)

atakann
atakann

Reputation: 1187

I have encountered this issue during my recent runs of pytest, and the reason was that I had pytest installed globally too.

The scenario is running pytest during your virtual environment is active, and you get errors, the reason is that the shell looks for pytest in your $PATH environment variable and it finds a pytest executable before it finds the one in your virtual environment which is associated with your system-wide Python installation.

In summary to solve this, by running,

python -m pytest

you tell Python to use pytest that is installed in the current Python environment.

By the way, -m flag is used to run a library module as a script (Execute module's __main__.py file).

Upvotes: 2

linpingta
linpingta

Reputation: 2620

I found this related question. For them it worked with this:

python -m pytest tests/my_test.py

I hope it works

Upvotes: 13

erny
erny

Reputation: 2489

I just wanted to run "black" for Python 2.7, but I have installed it in pyenv's Python 3.7.9. It worked correctly with the script /usr/local/bin/black27:

PYENV_VERSION=3.7.9 black -t py27 "$@"

It didn't work with:

pyenv shell 3.7.9
black -t py27 "$@"

nor

pyenv shell 3.7.9
pyenv exec black -t py27 "$@"

Upvotes: 2

ivan_pozdeev
ivan_pozdeev

Reputation: 36018

Bottom line: run

  • python -m pytest, or
  • py.test-<version> if your alternative Python and pytest are installed with system package manager, or
  • if your alternative Python has been installed with pyenv, switch with pyenv to that version and make sure you have pytest installed for it. Then you can just run pytest.
    • since the pip executable is also among the ones being switched, you need to switch to the alternative Python before installing pytest for it, too.

As I can see, /usr/bin/pytest (that belongs to the system package manager's python-pytest package) has a shebang !#/usr/bin/python since it corresponds to the system python's installation.

pyenv, as its README.md says, does not replace /usr/bin/python - because it indeed should not be replaced to avoid breaking system packages.

Instead, it adds its directory to PATH and inserts a launcher there (called "shim") which is what gets invoked when you type "python". As you probably guessed, this hack is ignored by a shebang like the above - as it should.

  • Running python -m pytest will make whichever python that launches itself use the package from its installation.
  • Alternatively, pytest for your other Python version may include versioned executables on the PATH named py.test-<version> (e.g. py.test-3 or py.test-3.6) depending on the way you installed it.
    • If it's from a system package manager's package for nonstandard python - like python36-pytest - this is virtually guaranteed.
    • I checked that if you install a version with pip, it only creates an unversioned executable (though you can create a versioned one yourself). Moreover, if you install the same package for a different Python version but with the same --prefix, it will overwrite the existing one's executable!
  • pyenv's suggested way seems to be to install all python versions of interest and packages for them under ~/.pyenv/versions.
    • This is not applicable for the system's Python but the default /usr/local can be used for it.
    • Once you switch to an alternative Python version, it claims to create shims for all scripts (including pip!) that are currently installed for that version, so invoking those scripts without a path would run those shims.
      • So, if a package (and thus its script) is not installed for the alternative version but installed for system version, trying to run its executable would "fall through" to /usr/local with just the result you're seeing now.

Upvotes: 45

Related Questions