【问题标题】:Python package import from parent directory从父目录导入 Python 包
【发布时间】:2012-07-08 18:13:37
【问题描述】:

我有以下源代码结构

/testapp/
/testapp/__init__.py
/testapp/testmsg.py
/testapp/sub/
/testapp/sub/__init__.py
/testapp/sub/testprinter.py

其中testmsg 定义了以下常量:

MSG = "Test message"

sub/testprinter.py:

import testmsg

print("The message is: {0}".format(testmsg.MSG))

但我收到了ImportError: No module named testmsg

它不应该从包结构开始工作吗?我真的不想在每个子模块中扩展 sys.path,我什至不想使用相对导入。

我在这里做错了什么?

【问题讨论】:

  • @SimeonVisser 运行 python sub/testprinter.py,但在 sub 目录中也运行 python testprinter.py 不起作用。

标签: python import package importerror


【解决方案1】:

这完全取决于您运行的脚本。该脚本的路径将自动添加到 python 的搜索路径中。

使其结构如下:

TestApp/
TestApp/README
TestApp/LICENSE
TestApp/setup.py
TestApp/run_test.py
TestApp/testapp/__init__.py
TestApp/testapp/testmsg.py
TestApp/testapp/sub/
TestApp/testapp/sub/__init__.py
TestApp/testapp/sub/testprinter.py

然后运行TestApp/run_test.py首先

from testapp.sub.testprinter import functest ; functest()

那么TestApp/testapp/sub/testprinter.py 可以这样做:

from testapp.testmsg import MSG
print("The message is: {0}".format(testmsg.MSG))

更多好提示here;

【讨论】:

  • 可能取决于我没有生成 setup.py 文件这一事实吗?我的意思是我遵循了python的包结构但是我没有生成安装方法,假设它也可以工作而不必setup.py install它。
  • @CodeShining,不,没关系。为了清楚起见,我只在示例中包含了setup.py。正如我在答案的第一段中所说,真正重要的是您首先运行的是哪个文件。如果您在包内启动(运行)文件,它将看不到包。因此,将主脚本(您运行的脚本)放在包之外是一种很好的做法。
【解决方案2】:

使用下面的相对导入

from .. import testmsg

【讨论】:

  • 但是作为一个包它不应该按预期工作吗?如果预计会起作用,我不会使用 relative
  • CodeShining,看看 Dido 对 python 3.5 PEP-328 标准的决定。 link
  • ValueError: attempted relative import beyond top-level package
  • @CameronHudson 相邻文件夹也需要是一个包(即有自己的__init__.py
【解决方案3】:

这个问题有答案——动态导入:

How to import a python file in a parent directory

import sys
sys.path.append(path_to_parent)
import parent.file1

这是我用来导入任何东西的东西。当然,你还是得把这个脚本复制到本地目录,导入,use你想要的路径。

import sys
import os

# a function that can be used to import a python module from anywhere - even parent directories
def use(path):
    scriptDirectory = os.path.dirname(sys.argv[0])  # this is necessary to allow drag and drop (over the script) to work
    importPath = os.path.dirname(path)
    importModule = os.path.basename(path)
    sys.path.append(scriptDirectory+"\\"+importPath)        # Effing mess you have to go through to get python to import from a parent directory

    module = __import__(importModule)
    for attr in dir(module):
        if not attr.startswith('_'):
            __builtins__[attr] = getattr(module, attr)

【讨论】:

    【解决方案4】:

    对于仍然有同样问题的人。我就是这样解决我的问题的:

    import unittest 
    import sys
    import os
    
    sys.path.append(os.getcwd() + '/..')
    
    from my_module.calc import *
    

    【讨论】:

    • 这节省了我的时间,我一直在搜索我的全部但没有结果,谢谢:)
    • cwd 并不总是正在运行的脚本的实际父级,正在运行的脚本是您当前的顶级。如果你想干预 sys.path,那么你应该使用 __file__ 的父级而不是 cwd 的父级
    【解决方案5】:

    试试这个:

    
    import sys
    import os
    sys.path.append(os.path.dirname(os.path.dirname(__file__)))
    
    from my_module import *
    
    

    【讨论】:

      猜你喜欢
      • 2016-12-27
      • 2013-11-09
      • 2020-03-21
      • 2021-08-15
      • 1970-01-01
      • 2015-07-23
      • 2021-10-23
      • 1970-01-01
      • 2021-09-08
      相关资源
      最近更新 更多