Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python 2.5中的相对导入_Python_Import_Relative Path_Python 2.5 - Fatal编程技术网

python 2.5中的相对导入

python 2.5中的相对导入,python,import,relative-path,python-2.5,Python,Import,Relative Path,Python 2.5,我知道Python中同样的导入问题有很多问题,但似乎没有人能够提供正确使用的清晰示例 假设我们有一个包mypackage,包含两个模块foo和bar。在foo内部,我们需要能够访问bar 因为我们还在开发它,mypackage不在sys.path中 我们希望能够: 导入mypackage.foo 将foo.py作为脚本运行,并从\uuuuu main\uuuu部分执行示例用法或测试 使用Python 2.5 我们必须如何在foo.py中进行导入,以确保它在所有这些情况下都能工作 # mypa

我知道Python中同样的导入问题有很多问题,但似乎没有人能够提供正确使用的清晰示例

假设我们有一个包
mypackage
,包含两个模块
foo
bar
。在
foo
内部,我们需要能够访问
bar

因为我们还在开发它,
mypackage
不在
sys.path

我们希望能够:

  • 导入
    mypackage.foo
  • foo.py
    作为脚本运行,并从
    \uuuuu main\uuuu
    部分执行示例用法或测试
  • 使用Python 2.5
我们必须如何在foo.py中进行导入,以确保它在所有这些情况下都能工作

# mypackage/__init__.py
...

# mypackage/foo/__init__.py
...

# mypackage/bar.py  
def doBar()
    print("doBar")

# mypackage/foo/foo.py
import bar # fails with module not found
import .bar #fails due to ValueError: Attempted relative import in non-package

def doFoo():
    print(doBar())

if __name__ == '__main__':
    doFoo()

请查看以下信息:

相对导入使用模块的
\uuuuu name\uuuu
属性来确定该模块在包层次结构中的位置。如果模块名称不包含任何程序包信息(例如,将其设置为
“\uuuuu main\uuuuuu”
),则将解析相对导入,就像模块是顶级模块一样,而不考虑模块在文件系统上的实际位置

当您以脚本形式运行
foo.py
时,该模块的
\uuuuu name\uuuuuuu
'\uuuuu main\uuuuuu'
,因此您无法进行相对导入。即使
mypackage
sys.path
上,这也是正确的。基本上,如果模块已导入,则只能从该模块进行相对导入

以下是解决此问题的几个选项:

1) 在
foo.py
中,检查
\uuuu name\uuuu=='\uuuuu main\uuuuu'
,并有条件地将
mypackage
添加到
sys.path

if __name__ == '__main__':
    import os, sys
    # get an absolute path to the directory that contains mypackage
    foo_dir = os.path.dirname(os.path.join(os.getcwd(), __file__))
    sys.path.append(os.path.normpath(os.path.join(foo_dir, '..', '..')))
    from mypackage import bar
else:
    from .. import bar
2) 始终使用mypackage导入栏中的
导入
,并执行
foo.py
,使
mypackage
自动可见:

$ cd <path containing mypackage>
$ python -m mypackage.foo.foo
$cd
$python-m mypackage.foo.foo

我的解决方案看起来更干净,可以与所有其他导入一起位于顶部:

try:
   from foo import FooClass
except ModuleNotFoundError:
   from .foo import FooClass

我认为您必须区分可导入模块和脚本。我不确定我是否同意这种设计,但这是我对它的理解。通常,当您需要从上层导入软件包时,您会出错:您是否希望将
bar
用作库而不是mypackage的子模块?也就是说,您能否将mypackage重构为mypackage1和mypackage2,其中mypackage2(带foo)导入mypackage1(带bar)?谢谢!唯一尚不清楚的是对包路径的检测。我明天会检查并返回结果。@sorin-我刚刚编辑了我的答案,因此无论从何处调用foo.py,您都可以获得mypackage的路径。在Windows上,我发现很少有
getcwd()
不提供脚本目录的情况。至少有3种方法可以调用python脚本:“python a.py”、“a.py”,并从Windows资源管理器(最终通过pythonw)@sorin运行-不幸的是,我只能在Linux上进行测试,我看到的行为是,
\uuu file\uuuu
要么是绝对路径,要么是从
os.getcwd()
foo.py
的路径。在这两种情况下,
foo\u dir
是指向包含
foo.py
的目录的绝对路径。不确定如果Windows不是这样,它需要如何更改。@sorin-如果您需要从bar使用
doBar
,您需要从mypackage.bar导入doBar
,或者从mypackage导入bar使用
,并将其命名为
bar.doBar()
。谢谢您的回答!它确实帮了我很多忙!