Incomplete sys.path with embeddable python (Windows)!?

Thomas Passin list1 at tompassin.net
Fri Apr 21 12:07:57 EDT 2023


On 4/20/2023 5:47 PM, Ralf M. wrote:
> Hello,
> 
> when I run a script with a "normally" installed python, the directory 
> the script resides in is automatically added as first element to 
> sys.path, so that "import my_local_module" finds my_local_module.py in 
> the directory of the script.
> 
> However, when I run the same script with embeddable python ("Windows 
> embeddable package (64-bit)", download link
> https://www.python.org/ftp/python/3.11.3/python-3.11.3-embed-amd64.zip) 
> the script directory is *not* prepended to the path, thus "import 
> my_local_module" gives an ImportError.
> 
> I couldn't find an option to get the "normal" behaviour. Any ideas how 
> to do that?
> 
> What I tried so far:
> 
> * The start-up value for sys.path seems to be defined in python311._pth. 
> It looks that I can add further static paths to it, but I don't know how 
> to make it add the script path (which can be different for different 
> scripts).
> 
> * Uncommenting "import site" in python311._pth doesn't help.
> 
> * It seems that I could import something else in python311._pth, but I 
> don't know how something imported from there could find out the path of 
> the script that is about to be started.
> 
> * I read the (rather short) documentation of the embeddable package and 
> of the site module several times but couldn't recognize a hint as to how 
> to solve the issue.
> 
> * I can add the following lines to every script:
>      import sys
>      script_path = __file__.rsplit("\\", 1)[0]
>      if script_path not in sys.path:
>          sys.path[0:0] = [script_path]
>      import my_local_modul
> That works, but it's ugly, executing code between imports is frowned 
> upon, and it needs to be added to every script.
> 
> Does anybody have a better idea?
> Any help is appreciated.

I haven't worked with embeddable python, but here are some possibilities 
that came to mind, depending on how your system works -

1. If your script is started from the command line, sys.argv[0] gives 
the path to the script; You could use os.path.dirname() to get its 
directory.  This will end up the same place as your code fragment, but 
looks nicer and handles different path separators (e.g., Linux vs Windows);

2. You could write a little module that figures out the script's path 
and import that first in all your scripts.

3. If you know all the directories that your scripts will be in, you 
could add them all to a xx.pth file (do a search to make sure where to 
put .pth files for an embeddable case).

Not executing code between imports is a guideline, but guidelines are 
not laws and you can certainly deviate from them if there is a good reason.

My preference would be for 1) if at all possible.  Something like this 
(untested) -

import sys
import os.path

script_dir = os.path.dirname(sys.argv[0])
sys.path.insert(0, script_dir)  # Use built-in method to insert

Inserting the path entry again in case it's already there is not harmful 
so there's no need to check.  If for some reason sys.argv is not 
available, just substitute __file__.  That still won't be too clunky.


More information about the Python-list mailing list