Nested env variables & PYTHONPATH

Hi there,
I have problems importing a module based on environment variables. I’m working on Windows 10.

My module is here:
D:/Boulot/processing/python/scripts/pouic_random/lib/basic.py

I added those env variables:
Path = %PYTHONPATH%
PYTHONPATH = 'C:/python37,%PROCESSING_LIB%'
PROCESSING_LIB = 'D:/work/processing/python'

:diamonds: This does not work:
import scripts.pouic_random.lib.basic as basic

ModuleNotFoundError: No module named ‘scripts’
[Finished in 0.1s with exit code 1]
[shell_cmd: python -u “C:\Users\Ben\Desktop\pyTest.py”]
[dir: C:\Users\Ben\Desktop]
[path: %PYTHONPATH%] (I cleaned this output so that stays readable)

%PYTHONPATH% does not seems to be unpacked in the error message while this works without any problem:

os.environ.get('Path')

C:\Python37;C:\Python37\Scripts;D:\Boulot\processing\python;

:diamonds: While this works:
import sys
sys.path.append(r'D:\Boulot\processing\python')
import scripts.pouic_random.lib.basic as basic

What seems to be the problem here? Does nested en var work this way? It seems strange that Sublime Text does not unpack %PYTHONPATH% in the error message.

I got the exact same problem if I put 'D:/work/processing/python' to Path or to PYTHONPATH.

Thanks!

Your PYTHONPATH env variable has a comma instead of a semicolon … That may be just a copy/paste error, but that could explain a lot of your behaviors.

1 Like

Did not know that :smiley: Thanks

Windows env variable options window seems completly broken, if I edit PYTHONPATH value, “Path” will not be modified through %PYTHONPATH% (eg if I remove a dir path in the nested one, Path will keep a non existing Path…)

So much for keeping a clean env. I’ll just dump everything in Path.

Hey there @bob.w, thanks for your answer.

If I remove %PYTHONPATH% from Path, then open cmd.exe and type “python”, Windows 10 will launch the Microsoft Store to download Python 3.7

I think you’re misunderstanding the difference between the environment variable PATH and the values found at sys.path.

For one thing you shouldn’t be overriding PATH with anything as that is a system wide variable that is used to find executables and binaries.

As to how PYTHONPATH works, any paths, separated by ; on windows as : on non-windows systems are added to sys.path during interpreter startup.
Nothing here is added to PATH.
If you need to extend path to search for some binaries, you’d do something like:
PATH = %PATH%;c:\my_new\path\to\somewhere

C:\tools>set python
Environment variable python not defined

C:\tools>set PYTHONPATH=c:\Advent_of_Code_2019

C:\tools>py
Python 3.8.0 (tags/v3.8.0:fa919fd, Oct 14 2019, 19:37:50) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.environ.get('PYTHONPATH')
'c:\\Advent_of_Code_2019'
>>> import sys
>>> for path in sys.path:
...  print(path)
...

c:\Advent_of_Code_2019
C:\Users\Regul\AppData\Local\Programs\Python\Python38\python38.zip
C:\Users\Regul\AppData\Local\Programs\Python\Python38\DLLs
C:\Users\Regul\AppData\Local\Programs\Python\Python38\lib
C:\Users\Regul\AppData\Local\Programs\Python\Python38
C:\Users\Regul\AppData\Roaming\Python\Python38\site-packages
C:\Users\Regul\AppData\Local\Programs\Python\Python38\lib\site-packages
>>>

So that sounds like python wasn’t added to your path when you did the initial install.
In which case it would be appropriate to add C:/python37 to your PATH.

I would do it along the lines of PATH = %PATH%;C:/python37 so that you can be assured that your original PATH settings aren’t overwritten.

Also depending on if you installed the launcher or not during your initial setup of python37, you might be able to get away with just typing py which is usually smart enough to track the locations that python was installed to through the official launcher.

I personally never add python.exe to PATH on my home machine these days, I just use py as an entry point.

I’ll follow your advice and use py, thanks.

Out of curiosity, how would you deal with a double installation (python 27 and 37 installed on the computer) to switch Python version between projects?

Python Launcher for Windows Version 3.8.150.1013

usage:
py [launcher-args] [python-args] script [script-args]

Launcher arguments:

-2     : Launch the latest Python 2.x version
-3     : Launch the latest Python 3.x version
-X.Y   : Launch the specified Python version
     The above all default to 64 bit if a matching 64 bit python is present.
-X.Y-32: Launch the specified 32bit Python version
-X-32  : Launch the latest 32bit Python X version
-X.Y-64: Launch the specified 64bit Python version
-X-64  : Launch the latest 64bit Python X version
-0  --list       : List the available pythons
-0p --list-paths : List with paths

The following help text is from Python:

usage: C:\Users\Regul\AppData\Local\Programs\Python\Python38\python.exe [option] ... [-c cmd | -m mod | file | -] [arg] ...
Options and arguments (and corresponding environment variables):
-b     : issue warnings about str(bytes_instance), str(bytearray_instance)
         and comparing bytes/bytearray with str. (-bb: issue errors)
-B     : don't write .pyc files on import; also PYTHONDONTWRITEBYTECODE=x
-c cmd : program passed in as string (terminates option list)
-d     : debug output from parser; also PYTHONDEBUG=x
-E     : ignore PYTHON* environment variables (such as PYTHONPATH)
-h     : print this help message and exit (also --help)
-i     : inspect interactively after running script; forces a prompt even
         if stdin does not appear to be a terminal; also PYTHONINSPECT=x
-I     : isolate Python from the user's environment (implies -E and -s)
-m mod : run library module as a script (terminates option list)
-O     : remove assert and __debug__-dependent statements; add .opt-1 before
         .pyc extension; also PYTHONOPTIMIZE=x
-OO    : do -O changes and also discard docstrings; add .opt-2 before
         .pyc extension
-q     : don't print version and copyright messages on interactive startup
-s     : don't add user site directory to sys.path; also PYTHONNOUSERSITE
-S     : don't imply 'import site' on initialization
-u     : force the stdout and stderr streams to be unbuffered;
         this option has no effect on stdin; also PYTHONUNBUFFERED=x
-v     : verbose (trace import statements); also PYTHONVERBOSE=x
         can be supplied multiple times to increase verbosity
-V     : print the Python version number and exit (also --version)
         when given twice, print more information about the build
-W arg : warning control; arg is action:message:category:module:lineno
         also PYTHONWARNINGS=arg
-x     : skip first line of source, allowing use of non-Unix forms of #!cmd
-X opt : set implementation-specific option
--check-hash-based-pycs always|default|never:
    control how Python invalidates hash-based .pyc files
file   : program read from script file
-      : program read from stdin (default; interactive mode if a tty)
arg ...: arguments passed to program in sys.argv[1:]

Other environment variables:
PYTHONSTARTUP: file executed on interactive startup (no default)
PYTHONPATH   : ';'-separated list of directories prefixed to the
               default module search path.  The result is sys.path.
PYTHONHOME   : alternate <prefix> directory (or <prefix>;<exec_prefix>).
               The default module search path uses <prefix>\python{major}{minor}.
PYTHONCASEOK : ignore case in 'import' statements (Windows).
PYTHONIOENCODING: Encoding[:errors] used for stdin/stdout/stderr.
PYTHONFAULTHANDLER: dump the Python traceback on fatal errors.
PYTHONHASHSEED: if this variable is set to 'random', a random value is used
   to seed the hashes of str and bytes objects.  It can also be set to an
   integer in the range [0,4294967295] to get hash values with a
   predictable seed.
PYTHONMALLOC: set the Python memory allocators and/or install debug hooks
   on Python memory allocators. Use PYTHONMALLOC=debug to install debug
   hooks.
PYTHONCOERCECLOCALE: if this variable is set to 0, it disables the locale
   coercion behavior. Use PYTHONCOERCECLOCALE=warn to request display of
   locale coercion and locale compatibility warnings on stderr.
PYTHONBREAKPOINT: if this variable is set to 0, it disables the default
   debugger. It can be set to the callable of your debugger of choice.
PYTHONDEVMODE: enable the development mode.
PYTHONPYCACHEPREFIX: root directory for bytecode cache (pyc) files.

You can get this help information by doing py --help
But the easiest way to swap between python 2/3 is with py -2 or py -3.
py --list will show all the python instations that the launcher knows about.

1 Like