2011-12-06 39 views
5

我在一个名为“project”的文件夹中有我的python代码,所以我的代码文件在project/* .py中。我想在其中有子模块,例如pythonic模块组织 - 如何引用根目录中的文件?

project/code.py # where code lives 
project/mymodule1 # where more code lives 
project/mymodule2 

每个模块目录有它自己的初始化 .py文件,例如

project/mymodule1/__init__.py 

假设我有mymodule1(项目/ mymodule1/test.py)内的文件“test.py”,我想指的是从“代码”的东西,例如导入功能“MYFUNC”

== project/mymodule1/test.py == 
from code import myfunc 

的问题是,“代码”不会被发现,除非用户已经放置了“项目/”目录中的PYTHONPATH。有没有办法避免这种情况,并使用某种“相对路径”来导入myfunc,例如

from ../code import myfunc 

基本上,我不想强​​迫代码的用户修改PYTHONPATH,除非我可以从我的脚本中以编程方式为他们做。我希望它可以开箱即用。

这怎么办?任何解决方案都是很好的:以编程方式更改PYTHONPATH,或者更理想的是,使用某种相对导入来引用“代码”,因为即使我不知道“project/code.py”在用户计算机上的位置,我知道在哪里它相对于“myfunc”。

编辑:有人可以显示内部包导入适当的例子吗?我想,从“mymodule1”做:

from .. import foo 

其中“富”是code.py,但它不工作。我在mymodule1 初始化的.py,所以:

project/code.py 
project/mymodule1/__init__.py 
project/mymodule1/module1_code.py 

其中module1_code.py尝试导入FOO,在 “code.py” 中定义的函数。

编辑:我仍然存在的主要困惑是,即使采用了响应我的消息给出的示例,显示项目/ sub1 /测试层次结构,您仍然不能“cd”到sub1中并执行“python test.py “并让它工作。用户必须在包含“project”的目录中并执行“import project.sub1.test”。无论用户在哪个目录下,我都希望这样工作。在这种情况下,用户必须执行位于project/sub1 /中的文件“test.py”。因此,测试案例是:

$ cd project/sub1 
$ python test.py 

其产生错误:

ValueError: Attempted relative import in non-package 

这可怎么固定?

感谢。

+0

'code.py'是否也导入'mymodule1/test.py'?如果是这样,你会想要重新组织你的代码。如果可能的话,应避免循环进口。 – Wilduck

回答

3

这在Python 2.5及更高版本中是可行的。请参阅Intra-Package References上的文档。

几件事情需要注意:

如果您打算让您的用户某处安装你的包,例如使用的distutils或setuptools的,那么project很可能已经在搜索路径,并可以将相对导入更改为from project.code import ...或类似。

如果您的用户正在将您的软件包安装到非标准目录(例如他们的主目录,其他不在sys.path等的其他位置),我的意见是它会减少混淆以指导用户修改PYTHONPATH而不是编程更改sys.path

如果你不打算让你的用户安装你的代码 - 例如,他们只是简单地解压缩源代码,cd到project的父目录,然后运行脚本 - 然后内部包装参考和相关进口可能会正常工作。

编辑:每个请求的,这里有一个例子:

假设封装布局如下:

project/ 
    __init__.py (empty) 
    code.py 
    sub1/ 
     __init__.py (empty) 
     test.py 

现在,project/code.py内容是:

# code.py (module that resides in main "project" package) 

def foo(): 
    print "this is code.foo" 

而且, project/sub1/test.py的内容是:

# test.py (module that resides in "sub1" subpackage of main "project" package) 

from ..code import foo 
foo() 

所以,test.py从相对路径..code,它采用封装内引用进口名foo让我们回到code.py模块内(这是..部分)sub1.test包,我们是执行。

为了测试这个:

shell$ (cd to directory where "project" package is located) 
shell$ python 
Python 2.6.1 (r261:67515, Aug 2 2010, 20:10:18) 
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import project.sub1.test 
this is code.foo 

注意的是,在from .. import X语法中的双点只是让你的父包,但你可以指定包内的模块。

换句话说,from .. import X在这种情况下,相当于from project import X,因此X必须是在project或内project/__init__.py类/功能/名称的模块。因此,from ..code import X相当于from project.code import X

+0

有人可以展示包内导入的正确示例吗?我试过,从“mymodule1”做到:从.. import foo,其中“foo”在code.py中,但它不起作用。我在mymodule1中有__init__.py – user248237dfsf

+0

@ user248237:看到我​​的修改后的回复包括一个例子。主要区别在于'from ... import foo'等同于搜索'project/__ init __。py',而不是'code.py'。 – bjlaub

+1

我没有得到的是为什么如果你cd到“sub1”,并执行:python test.py,你会得到错误“ValueError:试图相对导入非包” – user248237dfsf

1

避免这种情况的最佳方法是将所有代码保存在src文件夹中,或者将其命名为您的项目,例如,myproject并保持__init__.py那里,所以你可以做到这一点

from myproject import code 

使您的文件夹结构将是

project 
    main.py 
    myproject 
     __init__.py 
     code.py 
     module1 
     module2 

main.py或任何名字,你给它不应该有太多的代码,它应该得到所需的模块从myproject并运行它

from myproject import myapp 
myapp.run() 

看到好的article关于如何安排你的python项目。

+0

不解决问题 - 如何module1的代码可以调用上游定义的东西吗?在父母代表? – user248237dfsf

+0

myproject将在Python路径中,并且每个模块都可以导入任何模块,例如'from myproject.module1 import xxx' –

+0

1)我认为你的意思是'project'将在PYTHONPATH中,而不是'myproject'中,并且(2)否,如果进程是使用'python myproject/code.py'开始的, ,这是OP的情况,他的问题仍然没有解决,恕我直言, –