2011-12-06 73 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的情況,他的問題仍然沒有解決,恕我直言, –