from sub2 import mod2
。然后,在应用程序内部运行mod1需要执行python -m sub1.mod1
。 - Xiong Chiamiov下面是我用的解决方案:
我使用相对导入,例如 from ..sub2 import mod2
然后,如果我想运行mod1.py
,则进入app
的父目录,并使用python -m开关运行模块,如python -m app.sub1.mod1
.
相对导入出现问题的真正原因是它通过获取模块的__name__
属性来工作。如果直接运行模块,则会将__name__
设置为__main__
,并且不包含任何有关包结构的信息。这就是Python抱怨relative import in non-package
错误的原因。
因此,使用-m开关可以向Python提供包结构信息,从而成功解析相对导入。
在进行相对导入时,我遇到了这个问题很多次。在阅读了所有先前的答案之后,我仍然无法找出如何以干净的方式解决它,而无需在所有文件中添加样板代码。(尽管某些评论确实很有帮助,感谢@ncoghlan 和@XiongChiamiov)
希望这能帮助正在遭受相对导入问题的人,因为阅读PEP并不是一件有趣的事情。
-m
命令旨在解决的。 - MestreLionfrom . import some_module
。 - Rotareti$ PWD
是其父目录的情况下将脚本作为模块运行,例如 $ python -m app.main
**。为了清晰起见,应该使用 $ python -m <main_directory>.<script_with_relative_imports>
。 - Jesse H.main.py
setup.py
app/ ->
__init__.py
package_a/ ->
__init__.py
module_a.py
package_b/ ->
__init__.py
module_b.py
python main.py
。main.py
执行: import app.package_a.module_a
module_a.py
执行:import app.package_b.module_b
或者,2 或 3 可以使用:from app.package_a import module_a
只要在 PYTHONPATH 中有 app
即可。这样,main.py
可以放置在任何位置。
因此,您可以编写一个 setup.py
文件将整个应用程序包和子包复制(安装)到目标系统的 Python 文件夹中,将 main.py
复制到目标系统的脚本文件夹中。
"Guido认为在包内运行脚本是一种反模式"(被拒绝的PEP-3122)
我花了很多时间寻找解决方案,阅读了Stack Overflow上相关的帖子,并对自己说“一定有更好的方法!”。看起来并没有。
或从顶级脚本中调用
app.sub1.mod1.main()`(例如,从setup.py中定义的setuptools' entry_points生成)。 - jfs这个问题已经完全解决:
在 app/main.py 中导入 settings/local_setting.py:
main.py:
import sys
sys.path.insert(0, "../settings")
try:
from local_settings import *
except ImportError:
print('No Import')
sys.path.insert(0, "../settings")
,然后from local_settings import *
。 - Vit Bernatikpath
来查找模块。默认情况下,脚本所在的目录会被加入到路径中。这样强制将上一级目录中名为settings
的目录插入到路径中。就像所有的技巧一样,这种方法在很多情况下都能起作用,但并不是Python中导入模块的预期方式。其他方法更受推荐。 - CervEd通过示例解释nosklo的答案:
注意:所有__init__.py
文件都是空的。
main.py
app/ ->
__init__.py
package_a/ ->
__init__.py
fun_a.py
package_b/ ->
__init__.py
fun_b.py
def print_a():
print 'This is a function in dir package_a'
from app.package_a.fun_a import print_a
def print_b():
print 'This is a function in dir package_b'
print 'going to call a function in dir package_a'
print '-'*30
print_a()
from app.package_b import fun_b
fun_b.print_b()
python main.py
,它会返回:This is a function in dir package_b
going to call a function in dir package_a
------------------------------
This is a function in dir package_a
from app.package_b import fun_b
from app.package_a.fun_a import print_a
因此,位于package_b
文件夹中的文件使用了位于package_a
文件夹中的文件,这正是您想要的。对吗?
使用:
def import_path(fullpath):
"""
Import a file with full path specification. Allows one to
import from anywhere, something __import__ does not do.
"""
path, filename = os.path.split(fullpath)
filename, ext = os.path.splitext(filename)
sys.path.append(path)
module = __import__(filename)
reload(module) # Might be out of date
del sys.path[-1]
return module
很不幸,这是一种 sys.path 的hack方法,但它非常有效。
我遇到了另一个层面的问题:我已经有了一个指定名称的模块,但它是错误的模块。
我想要做的是以下内容(我正在使用的模块是 module3):
mymodule\
__init__.py
mymodule1\
__init__.py
mymodule1_1
mymodule2\
__init__.py
mymodule2_1
import mymodule.mymodule1.mymodule1_1
请注意,我已经安装了mymodule,但在我的安装包中找不到“mymodule1”
因为它试图从我安装的模块中进行导入,所以我会收到ImportError错误。
我尝试过sys.path.append,但那并没有起作用。能够起作用的是sys.path.insert
if __name__ == '__main__':
sys.path.insert(0, '../..')
有点取巧,但是我把所有东西都搞定了! 需要记住的是,如果你想要你的决策<强制覆盖其他路径>,那么你需要使用sys.path.insert(0, pathname)来使其生效!这对我来说是一个非常令人沮丧的难点,很多人说要使用 "append" 函数到sys.path中,但是如果你已经定义了一个模块,那么它就不起作用了(我认为这是一种非常奇怪的行为)
sys.path.append('../')
对我来说很有效(Python 3.5.2) - Nister这里只是为了自己参考而放置。我知道这不是好的Python代码,但我需要一个脚本来完成我的项目,并且我想把这个脚本放在scripts
目录下。
import os.path
import sys
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
正如EvgeniSergeev在评论中所说的那样,您可以使用以下代码从任意位置导入.py
文件:
import imp
foo = imp.load_source('module.name', '/path/to/file.py')
foo.MyClass()
这段内容来自这个Stack Overflow回答。