Mr_*_*s_D 22 python python-import python-2.7 relative-import python-unittest
这是我的文件夹结构:
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
Run Code Online (Sandbox Code Playgroud)
在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
Run Code Online (Sandbox Code Playgroud)
在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()
Run Code Online (Sandbox Code Playgroud)
现在当我发出:
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
Run Code Online (Sandbox Code Playgroud)
我明白了:
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
Run Code Online (Sandbox Code Playgroud)
由于'Mopy'在sys.path中并且bosh\__init__.py正确解析了为什么它抱怨顶级包之上的相对导入?哪个是顶级包?
顺便提一下,这是我尝试将测试添加到遗留项目中 - 已经在Python测试包布局中询问但是作为Python单元测试的位置的副本被关闭了吗?.对我目前的测试包布局的评论非常感谢!
该模块 bash.py是入口点到包含应用:
if __name__ == '__main__':
main()
Run Code Online (Sandbox Code Playgroud)
当我使用import bash.bosh或from 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
Run Code Online (Sandbox Code Playgroud)
此用法消息来自bash中的main().
Mis*_*agi 26
TLDR:做
import bash.bosh
Run Code Online (Sandbox Code Playgroud)
要么
from bash import bosh
Run Code Online (Sandbox Code Playgroud)
如果你碰巧有类似的结构bash.bash,你必须确保你的包优先于其内容.而不是追加,将其添加到搜索顺序的前面:
# test_bash\__init__.py
sys.path.insert(0, mopy)
Run Code Online (Sandbox Code Playgroud)
当你这样做
import bosh
Run Code Online (Sandbox Code Playgroud)
它将导入模块 bosh.这意味着Mopy/bash在你的sys.pathpython中找到bosh那里的文件,并导入它.该模块现在以名称全球闻名bosh.无论bosh是本身就是一个模块或包不要紧此,它只会改变是否bosh.py或bosh/__init__.py使用.
现在,当bosh试图做
from .. import bass
Run Code Online (Sandbox Code Playgroud)
这不是文件系统操作("一个目录,文件低音"),而是模块名称操作.这意味着"一个包装升级,模块低音".bosh但是它不是从它的包中导入的,而是它自己的.所以不可能上一个包 - 你最终在包'',这是无效的.
让我们来看看你做什么时会发生什么
import bash.bosh
Run Code Online (Sandbox Code Playgroud)
代替.首先,导入包 bash.然后,bosh作为该软件包的模块导入- bash.bosh即使您使用过,它也是全局知道的from bash import bosh.
什么bosh时候
from .. import bass
Run Code Online (Sandbox Code Playgroud)
那一个现在有效:从一级升级bash.bosh到达bash.从那里,bass导入为bash.bass.
另请参阅此相关答案,以便在不修改的情况下从包中执行模块sys.path.
| 归档时间: |
|
| 查看次数: |
40570 次 |
| 最近记录: |