Search code examples
pythonwindowsshebangpath-variables

Why can't the Python launcher import in a script (with shebang), when it works in the interpreter?


I'm using the py Python launcher, and something weird is happening with imports. Certain modules can't be imported in scripts - despite being installed with pip and being importable in the interpreter. Here's the kicker, though: it works in scripts without the shebang line.

For example, this script works:

import requests

But this one doesn't:

#!/usr/bin/env python
import requests

Why is this? What difference is the shebang making here?


Solution

  • The py launcher actually handles shebang lines even on Windows. This means the Python version a script is run in may differ depending on the shebang line. For example, a shebang line of #!/usr/bin/env python2 will always run Python 2, and #!/usr/bin/env python3 will always run Python 3. Without a shebang line, py pretends the shebang is !python, which it handles using its built-in rules for selecting a Python version (see the Python Version Qualifiers section). By default, if you have it installed, this will be some version of Python 2.

    Here's what's tripping you up, though. If the shebang is specifically !/usr/bin/env python, py instead follows the PATH environment variable to mimic the behavior of Linux's env (see the last paragraph), and only after that falls back on the normal behavior. This means scripts with the shebang might be running under a different Python version than py normally invokes, depending on what's in your PATH. This is what's happening here - #!/usr/bin/env python is finding another Python version on the path, and using that instead. That version might not have the modules you pip installed installed, and might therefore fail.

    Since you're using py, you shouldn't have a python on your PATH, so remove any Python base directory entries from your PATH (e.g. C:\Python35), or make sure the first Python on the PATH is the default one used by py, and everything should work just fine.

    Why py doesn't try to follow the path by default (or when the shebang is !python), however, is anyone's guess.