尝试在顶级包之外进行相对导入

2024-09-24 22:19:10 发布

您现在位置:Python中文网/ 问答频道 /正文

这是我的文件夹结构:

Mopy/ # no init.py !
   bash/
     __init__.py
     bash.py # <--- Edit: yep there is such a module too
     bass.py
     bosh/
       __init__.py # contains from .. import bass
       bsa_files.py
     ...
   test_bash\
     __init__.py # code below
     test_bosh\
       __init__.py
       test_bsa_files.py

test_bash\__init__.py我有:

import sys
from os.path import dirname, abspath, join, sep
mopy = dirname(dirname(abspath(__file__)))
assert mopy.split(sep)[-1].lower() == 'mopy'
sys.path.append(mopy)
print 'Mopy folder appended to path: ', mopy

test_bsa_files.py中时:

import unittest
from unittest import TestCase

import bosh

class TestBSAHeader(TestCase):
    def test_read_header(self):
        bosh.bsa_files.Header.read_header()

if __name__ == '__main__':
    unittest.main()

现在当我发布:

python.exe "C:\_\JetBrains\PyCharm 2016.2.2\helpers\pycharm\utrunner.py" C:\path\to\Mopy\test_bash\test_bosh\test_bsa_files.py true

我得到:

Traceback (most recent call last):
  File "C:\_\JetBrains\PyCharm 2016.2.2\helpers\pycharm\utrunner.py", line 124, in <module>
    modules = [loadSource(a[0])]
  File "C:\_\JetBrains\PyCharm 2016.2.2\helpers\pycharm\utrunner.py", line 43, in loadSource
    module = imp.load_source(moduleName, fileName)
  File "C:\Dropbox\eclipse_workspaces\python\wrye-bash\Mopy\test_bash\test_bosh\test_bsa_files.py", line 4, in <module>
    import bosh
  File "C:\Dropbox\eclipse_workspaces\python\wrye-bash\Mopy\bash\bosh\__init__.py", line 50, in <module>
    from .. import bass
ValueError: Attempted relative import beyond toplevel package

因为'Mopy'在sys.path中,bosh\__init__.py被正确地解决了,为什么它抱怨顶级包之上的相对导入?哪个是顶级套餐?

顺便说一句,这是我试图将测试添加到遗留项目中的尝试-在Python test package layout中请求,但作为Where do the Python unit tests go?的副本关闭。对我目前的测试包布局的意见是非常感谢!


那么answer below在我的情况下不起作用:

模块bash.py是应用程序的入口点,它包含:

if __name__ == '__main__':
    main()

当我使用import bash.boshfrom bash import bosh时,我得到:

C:\_\Python27\python.exe "C:\_\JetBrains\PyCharm 2016.2.2\helpers\pycharm\utrunner.py" C:\Dropbox\eclipse_workspaces\python\wrye-bash\Mopy\test_bash\test_bosh\test_bsa_files.py true
Testing started at 3:45 PM ...
usage: utrunner.py [-h] [-o OBLIVIONPATH] [-p PERSONALPATH] [-u USERPATH]
                   [-l LOCALAPPDATAPATH] [-b] [-r] [-f FILENAME] [-q] [-i]
                   [-I] [-g GAMENAME] [-d] [-C] [-P] [--no-uac] [--uac]
                   [--bashmon] [-L LANGUAGE]
utrunner.py: error: unrecognized arguments: C:\Dropbox\eclipse_workspaces\python\wrye-bash\Mopy\test_bash\test_bosh\test_bsa_files.py true

Process finished with exit code 2

此用法消息来自bash中的main()。


Tags: pathfrompytestimportbashinitmain
1条回答
网友
1楼 · 发布于 2024-09-24 22:19:10

TLDR:做

import bash.bosh

或者

from bash import bosh

如果您刚好有一个类似bash.bash的结构,那么您必须确保您的包优先于它的内容。将其添加到搜索顺序的前面,而不是附加:

# test_bash\__init__.py
sys.path.insert(0, mopy)

当你这样做的时候

import bosh

它将导入模块bosh。这意味着Mopy/bash在您的sys.path中,python在那里找到文件bosh,然后导入它。该模块现在是全局已知的名称bosh。不管bosh本身是模块还是包,这都无关紧要,它只会更改使用bosh.py还是bosh/__init__.py

现在,当bosh试图

from .. import bass

这不是一个文件系统操作(“one directory up,file bass”),而是一个模块名操作。它的意思是“一个包水平,模块低音”。bosh不是从包中导入的,而是自己导入的。因此,向上一个包是不可能的-您最终会到达包'',这是无效的。

让我们看看当你这样做的时候

import bash.bosh

相反。首先,导入bash。然后,bosh作为包的模块导入,它被全局称为bash.bosh,即使您使用了from bash import bosh

bosh这样做时

from .. import bass

那一个现在起作用了:从bash.bosh上升一级,你就可以到达bash。从那里,bass作为bash.bass导入。

另请参见this related answer,以在不修改sys.path的情况下从包内执行模块。

相关问题 更多 >