当使用._pth文件时,脚本目录未包含在sys.path中

9
我正在尝试解决一个奇怪的问题,与在我编写的Python脚本中导入模块有关。实现该模块的文件位于与主Python脚本相同的目录中。
当我使用ActivePython时,Python脚本可以正常工作。然而,当我使用嵌入式分发时,就会出现以下错误。
ModuleNotFoundError: No module named 'pyWhich'

我已经追踪到了行为差异的原因,这是由于嵌入式分发中sys.path变量的设置方式不同。在我的脚本可以工作的ActivePython环境中,sys.path的第一个条目是包含脚本的目录。但是,在嵌入式分发中,没有包含脚本的目录的条目。嵌入式分发使用_pth文件来设置sys.path。我正在使用默认的._pth文件,下面是为您方便起见包含的内容。
python36.zip
.

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

我的问题是,我需要在我的_pth文件中添加什么神奇的咒语来告诉Python将包含任何运行脚本的目录放入sys.path中,以便我的脚本可以与嵌入式分发一起使用。path configuration files上的文档似乎没有包含这些信息。请保留HTML标签。
3个回答

2
我仍然希望有一个神奇的咒语可以添加到我的_pth文件中,它会说:“请将任何我运行的脚本所在的目录放入sys.path”,这样我就不必修改所有的脚本了。然而,可能不存在这样的神奇咒语。
我发现,当将以下神奇咒语添加到Python脚本中时,可以实现所需的结果。与您在其他地方找到的其他解决方案不同,这个解决方案适用于cx_Freeze和IDLE以及任何其他简单的基于文件的解决方案无法解决的情况。
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())

顺便说一下,如果你想看到它的实际效果,我已经在我的 Python项目 中实现了它。

0
你尝试过使用sys.path.append('C:/documents/folder/blah...')吗?(当然要替换成正确的文件夹路径)

我猜你的意思是询问我是否尝试修改脚本本身?如果是这样,我没有。如果必须这样做,我会去尝试,但我更喜欢通过一次性更改_pth文件来解决这个问题。 - Benilda Key
请查看我在 https://dev59.com/aGoy5IYBdhLWcg3wQ78F#50025581 的回答,了解我为什么希望避免“只需修改脚本以将目录添加到sys.path”方法。我有多个项目,如果不必要,我不想被迫将所有代码添加到每个项目中。 - Benilda Key
完全同意。我想我一段时间前也遇到了这个问题,并被迫使用这种方法来解决……但我需要让代码运行,而这种方法虽然不理想,但在最后关头是足够好的。 - user3376851

0
我的解决方案是删除这个文件:
python39._pth

这样可以让Pip工作,并且允许从同一目录中import。 或者你也可以使用以下方法:

https://nuget.org/packages/python

点击“下载包”按钮,你可以像解压Zip文件一样进行提取。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接