9

I am attempting to solve a weird issue related to importing modules in a Python script I have written. The file that implements the module is in the same directory as the main Python script.

The Python script works perfectly when I use ActivePython. However, when I use the Embedded Distribution I get the following error.

ModuleNotFoundError: No module named 'pyWhich'

I have traced the difference in behavior to the way the sys.path veritable is set in the Embedded Distribution.

In ActivePython, the environment in which my script works, the first entry in sys.path is the directory containing the script. In the Embedded Distribution, there is no entry for the directory containing the script.

The Embedded Distribution uses a _pth file to set the sys.path. I am using the default ._pth file, which I have included below for your convenience.

python36.zip
.

# Uncomment to run site.main() automatically
#import site

My question is, what magical incantation do I need to add to my _pth file to tell Python to please put the directory containing any script I run in sys.path so my scripts will work with the Embedded Distribution. The documentation on path configuration files does not seem to contain this information.

Benilda Key
  • 2,836
  • 1
  • 22
  • 34

3 Answers3

2

I am still hoping for a magical incantation I can add to my _pth file that says "please put the directory containing any script I run in sys.path" so I do not have to modify all my scripts. However, it is possible that no such magical incantation exists.

I have found that the following magical incantation, when added to a Python script, achieves the desired results. And, unlike other solutions you may find out there in the wild, this one will work in the context of cx_Freeze and IDLE and in any other context in which the simple file based solutions will not work.

import inspect
import os
import sys

# Add script directory to sys.path.
# This is complicated due to the fact that __file__ is not always defined.

def GetScriptFile():
    """Obtains the full path and file name of the Python script."""
    if hasattr(GetScriptFile, "file"):
        return GetScriptFile.file
    ret = ""
    try:
        # The easy way. Just use __file__.
        # Unfortunately, __file__ is not available when cx_freeze is used or in IDLE.
        ret = os.path.realpath(__file__)
    except NameError:
        # The hard way.
        if len(sys.argv) > 0 and len(sys.argv[0]) > 0 and os.path.isabs(sys.argv[0]):
            ret = os.path.realpath(sys.argv[0])
        else:
            ret = os.path.realpath(inspect.getfile(GetScriptFile))
            if not os.path.exists(ret):
                # If cx_freeze is used the value of the ret variable at this point is in
                # the following format: {PathToExeFile}\{NameOfPythonSourceFile}. This
                # makes it necessary to strip off the file name to get the correct path.
                ret = os.path.dirname(ret)
    GetScriptFile.file = ret
    return GetScriptFile.file

def GetScriptDirectory():
    """Obtains the path to the directory containing the script."""
    if hasattr(GetScriptDirectory, "dir"):
        return GetScriptDirectory.dir
    module_path = GetScriptFile()
    GetScriptDirectory.dir = os.path.dirname(module_path)
    return GetScriptDirectory.dir

sys.path.insert(0, GetScriptDirectory())

By the way, if you wish to see this in action, I have implement it my my Python Which project.

Benilda Key
  • 2,836
  • 1
  • 22
  • 34
0

Have you tried sys.path.append('C:/documents/folder/blah...') (with the correct folder location ofc)

user3376851
  • 149
  • 10
  • I assume you mean to ask if I attempted to modify the script itself? If so, I have not. I will do that if I must but I prefer to solve this problem with a one time change, to the _pth file. – Benilda Key Apr 25 '18 at 14:15
  • See my answer to https://stackoverflow.com/a/50025581/2532437 for information on why I was hoping to avoid the "just modify the script to add the directory to sys.path" approach. I have more than one project and I do not want to be forced to add all that code to every project if I do not have to. – Benilda Key Apr 25 '18 at 15:05
  • Completely agree. I think I had this problem a while back and resorted to using this method as a bodge... But I needed the code to work and the bodge meant it worked in time - not ideal but good enough as last resort – user3376851 Apr 26 '18 at 12:18
0

Solution for me was deleting this file:

python39._pth

This allows Pip to work, and also allow import from same directory. Alternatively you can get this:

https://nuget.org/packages/python

Click "Download package", and you can extract just like a Zip file.

Zombo
  • 1
  • 62
  • 391
  • 407