2016-08-17 53 views
2

假設我有一個文件夾Awesome_stuff/my_module,它包含以下文件:my_algorithm.py,my_settings.py,my_utils.py。 主文件my_algorithm.py包含以下行:使子模塊在同一Python模塊內彼此可見

# my_algorithm.py 
import my_utils as mu 
from my_settings import My_settings 

def alg(): 
    # do something 

if __name__ == "__main__": 
    alg() 

運行python my_algorithm.py不會產生任何問題。然而,如果我想在我的Python庫中安裝這個模塊,事情就會改變。爲了做到這一點,我添加一個空__init__.py文件my_module文件夾中的my_module文件夾內,外,我把一個setup.py文件看起來像這樣:

from setuptools import setup 

setup(
    name = 'Awesome_stuff', 
    version = '1.0.0', 
    packages = ['my_module'], 
    # # dependencies 
    install_requires = ['numpy','scipy', 'numpydoc>=0.5', 'pyomo>=4.3.11388', 'mock>=1.1.3'], 
    # # project metadata 
    author = 'Me', 
    author_email = '[email protected]', 
    description = 'This module contains awesome stuff', 
    license = 'BSD', 
    url = 'http://my_website.com', 
    download_url = 'my_download_address.com' 
) 

運行python setup.py install產生卵子和模塊安裝在我的Python圖書館。現在主要的文件夾Awesome_stuff包含:

Awesome_stuff.egg-info 
build (folder created during installation) 
dist (folder created during installation) 
my_module (my original folder plus __init__.py) 
setup.py 

爲了執行一些等同於原來的python my_algorithm.py我現在可以創建包含有類似from my_module.my_algorithm import *一個新的Python文件test.py,然後執行alg()

不幸的是,線from my_module.my_algorithm import *生成以下錯誤:

Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "build/bdist.macosx-10.11-intel/egg/my_module/my_algorithm.py", line 25, in <module> 
ImportError: No module named my_utils 

我怎樣才能解決這個問題,而無需修改原來的三個模塊的文件?我看不出這裏出了什麼問題。

此外,import my_module不會產生任何錯誤。我在這裏有點困惑。 當模塊是獨立文件夾時,爲什麼從同一文件夾導入子模塊並在Python庫中安裝時無法工作?

更一般的問題:導入/使用可能相互依賴的子模塊的正確/建議的方式是什麼?文件__init__.py可能在這種情況下起作用嗎?

感謝。

OS X埃爾隊長,Python的2.7.10

EDIT

作爲一個例子,我看着Python庫Zen,其以類似的方式構造:

Zen 
    build 
    zen 
     folder1 
     folder2 
     ... 
     __init__.py 
     graph.pxd 
     graph.pyx 
     digraph.pxd 
     digraph.pyx 
     ... 
    Makefile 
    setup.py 

在這種情況下,digraph.pyx(即覆蓋一些graph.pxd聲明)包含行from graph cimport *,這當然不會導致任何問題。請注意,它不會說:from zen.graph cimport *

最後的編輯

當使用cimport你可以以設置*.pxd文件的路徑定義package_datasetup.py。這就是爲什麼cimport不需要上面例子中的絕對導入。但是,對於*.py文件(據我所知),這是不可能的,唯一的方法是使用絕對和相對導入。

回答

3

由於您添加了__init__.py文件,因此您已經制作了一個包。所以,現在,從包中導入時必須使用該包名稱:

# my_algorithm.py 
import my_module.my_utils as mu 
from my_module.my_settings import My_settings 

def alg(): 
    # do something 

if __name__ == "__main__": 
    alg() 
+0

是的,這樣可以解決問題,但似乎並不正確。在正式創建模塊之前和之後,模塊和子模塊的名稱空間和層次結構應該是等效的。否則,只有因爲他決定創建一個模塊而需要返回並修改所有「import ...」。 – Gioker

+0

@Gioker是的,好吧,他們不是。抱歉。在添加'__init__'之前,沒有適當的名稱空間。你還沒有創建一個模塊。你已經有了單獨的模塊。你將它們組合成一個包。 –

+0

@Gioker絕對導入是推薦的方式: https://www.python.org/dev/peps/pep-0008/#imports –