【问题标题】:Importing from parent directory in sub folder's file using __init__?使用 __init__ 从子文件夹文件中的父目录导入?
【发布时间】:2016-12-25 13:36:52
【问题描述】:

如果我有这样的目录

dir_one/
    main.py
    __init__.py
    dir_two/
        sub.py
        __init__.py

我的两个 init.py 文件目前都是空的。在我的 sub.py 文件中,我尝试从 main.py 导入一个类: 例如

#File:sub.py
from main import items

这没有用。我也试过了

#File:sub.py
from dir_one.main import items

这也没用。

有没有办法从sub.py 导入main.py 文件? __init__.py 是空的,我需要编辑它吗?

【问题讨论】:

  • 你在调用什么脚本?您是否尝试直接运行sub.py(a.la python dir_one/dir_two/sub.py)?或者您是从其他地方导入sub.py 并且此时它失败了?
  • 我正在尝试直接运行 sub.py
  • 啊——这就是问题所在。通常,包中的模块并不意味着直接运行。通常这些东西的结构方式是你应该有一个单独的目录(例如scripts,它导入包(和其中的实用程序),它提供了程序的入口点。
  • 意思是说一般模块不会相互导入,而是另一个非模块脚本导入模块?
  • 模块可以相互导入(通常使用"package-relative imports"),但前提是首先导入了包或您有__package__ 变量。这意味着你的 __main__ 模块不能在包中,除非它有一个 __package__ 变量..

标签: python import directory


【解决方案1】:

这里有几个选项。

您最好的选择是将包与使用该包的脚本分开。查看entry_points 的设置工具。您将 setuptools 指向包中的一个函数,它会创建一个脚本来调用它。漂亮...

在解决这个问题时,我设置了以下包结构:

test_dir
   + __init__.py
   + main.py
   + sub1
   --+ __init__.py
   --+ script.py
   + sub2
   --+ __init__.py
   --+ module.py

我已确保可以通过 PYTHONPATH 访问 test_dir

脚本都超级简单(只是打印一些东西):

# main.py
def func_in_main():
    print("Hello from main.py!")

# module.py
def run_func():
    print("Hello from script in sub2.py!")

# script.py
from ..sub2 import module
from .. import main

def entry_point():
    module.run_func()
    main.func_in_main()

if __name__ == '__main__':
    entry_point()

现在,如果我尝试直接运行它会发生什么?

$ python test_package/test_dir/sub1/script.py 
Traceback (most recent call last):
  File "test_package/test_dir/sub1/script.py", line 2, in <module>
    from ..sub2 import module
ValueError: Attempted relative import in non-package

嗯......真是太糟糕了(这就是我试图在你原来的问题的 cmets 中描述的情况)。顺便说一句,无论我当前的工作目录如何,都会发生这种情况......但是,我可以在我的文件系统上的任何地方使用-m标志运行它1

$ python -m test_dir.sub1.script 
Hello from script in sub2.py!
Hello from main.py!

万岁!我们只需要指定模块路径,然后我们就可以了(请记住,test_dir 必须可以通过您的 PYTHONPATH 访问才能正常工作)。好的,但是如果我们真的想调用脚本而不是使用模块路径怎么办?如果是这种情况,我们可以在进行任何导入之前修改 __package__ 变量:

# script.py (updated)
if __name__ == '__main__' and __package__ is None:
    __package__ = 'test_dir.sub1'
    import test_dir  # needed to suppress SystemError -- I'm not sure why...

from .. import main
from ..sub2 import module

def entry_point():
    module.run_func()
    main.func_in_main()

if __name__ == '__main__':
    entry_point()

现在让我们尝试再次直接运行这个东西:

$ python test_package/test_dir/sub1/script.py 
test_package/test_dir/sub1/script.py:4: RuntimeWarning: Parent module 'test_dir.sub1' not found while handling absolute import
  import test_dir
Hello from script in sub2.py!
Hello from main.py!

我们仍然得到RuntimeWarning,但它运行正常。更多详情,请查看PEP-0366

1一般来说,我已经从包外部运行了大部分这些(比test_dir 高一级),但是如果我从内部运行它,这些示例仍然有效 包也是如此。使用-m,您始终指定模块的完整路径(test_dir.sub1.script),没有它,您只需指定文件的相对或绝对路径)

【讨论】:

    【解决方案2】:

    在您的文件 sub.py 中,您可以执行类似的操作

    import os
    
    wd = os.getcwd()    # save current working directory
    os.chdir('path/to/dir_one')    # change to directory containing main.py  
    from main import items    # import your stuff
    os.chdir(wd)    # change back to directory containing sub.py
    

    在使用您的项目表单之前。

    编辑:在您的特定情况下,'path/to/dir_one' 只是向上一个目录,即'..'

    【讨论】:

      猜你喜欢
      • 2018-10-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-22
      • 1970-01-01
      • 2023-01-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多