[英]Python Relative Path Import: Import packages from another project directory
[英]Do I need to add my project directory to the system path in every script to import a function from another directory?
我正在努力保持數據科學項目組織良好,所以我在我的src
目錄中創建了一個名為utils
目錄,其中包含一個名為helpers.py
的文件,其中包含一些將在許多腳本中使用的輔助函數。 如何將func_name
從src/utils/helpers.py
導入到完全不同的目錄(例如src/processing/clean_data.py
的文件的最佳實踐是什么?
我看到了這個問題的答案 ,我已經實現了一個有效的解決方案,但這感覺很難看:
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))))
我這樣做了嗎? 我是否需要將此添加到每個要導入func_name
腳本中,例如train_model.py
?
我當前的項目文件夾結構:
myproject
/notebooks
notebook.ipynb
/src
/processing
clean_data.py
/utils
helpers.py
/models
train_model.py
__init__.py
示例文件:
# clean_data.py
import os
import sys
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))))
from src.utils.helpers import func_name
func_name()
# helpers.py
def func_name():
print('I'm a helper function.')
正確的方法是使用__init__.py
. setuptools
, setup.py
和setuptools
Python包:
myPackage/
myPackage/
__init__.py
setup.py
此鏈接包含所有步驟。
首先,讓我描述一下Python模塊和Python包之間的區別,以便我們兩個人都在同一頁面上。 ✌
import aModuleName # Here 'aModuleName' is just a regular .py file.
__init__.py
文件。 ✔ from aPackageName import aModuleName # Here 'aPackageName` is a folder with a `__init__.py` file # and 'aModuleName', which is just a regular .py file.
因此,當我們有一個名為proj-dir的項目目錄時,結構如下⤵
proj-dir --|--__init__.py --package1 --|--__init__.py --|--module1.py --package2 --|--__init__.py --|--module2.py
🔎請注意,我還在proj-dir本身添加了一個空的
__init__.py
,這也使它成為一個包。
👍現在,如果你想從包2的模塊2導入任何Python對象到包1的模塊1,然后在文件module1.py import語句會
from package2.module2 import object2 # if you were to import the entire module2 then, from package2 import module2
首先讓我澄清一下,如果要使用其中的一部分,導入整個模塊,則不是一個好主意。 而不是你可以使用from
來導入庫/包下的特定功能。 通過這樣做,您可以使您的程序在內存和性能方面更高效。
要了解更多信息,請參考以
網讓我們看看解決方案。
在開始使用解決方案之前,讓我向您闡明__init__.py
文件的用法。 它告訴python解釋器,存在的* .py文件是可導入的,這意味着它們是模塊, 並且/可能是包的一部分。
因此,如果您沒有N個子目錄,則必須將__init__.py
文件放在所有這些子目錄中,以便它們也可以導入。 在__init__.py
文件中,您還可以添加一些其他信息,例如應包含哪些路徑,默認函數,變量,范圍等等。 要了解這些只是谷歌關於__init__.py
文件或采取一些python庫並通過相同的__init__.py
文件來了解它。 (這就是解決方案)
更多信息:
正如@Sushant Chaudhary所說,你的項目結構應該是這樣的
proj-dir
--|--__init__.py
--package1
--|--__init__.py
--|--module1.py
--package2
--|--__init__.py
--|--module2.py
那么現在,如果我把
__init__.py
文件放在我上面的目錄下,它是否可以導入並且工作正常?是的,不 。
如果要導入該項目/包目錄中的模塊。 例如在你的情況下
您正在from package1 import module1
module1導入pakage2.module2中from package1 import module1
。
在這里你必須導入子模塊內的基礎目錄 , 為什么? 如果從同一個地方運行模塊,項目將運行正常。 ie:在package2中作為python module2.py , 但是會拋出ModuleNotFoundError
如果從其他目錄運行模塊。 ie:除了package2之外的任何其他路徑 ,例如在proj-dir下作為python package2/module2.py
。 這就是你的情況。 您正在從project-dir運行該模塊。
那么如何解決這個問題呢?
1-您必須在module2.py中將基於路徑的路徑附加到系統路徑
from sys import path
dir_path = "/absolute/path/to/proj-dir"
sys.path.insert(0, dir_path)
因此module2將能夠找到package1(以及其中的module1)。
2-您必須在proj-dir下的__init__.py
文件中添加所有子模塊路徑。
例如:
#__init__.py under lxml
# this is a package
def get_include():
"""
Returns a list of header include paths (for lxml itself, libxml2
and libxslt) needed to compile C code against lxml if it was built
with statically linked libraries.
"""
import os
lxml_path = __path__[0]
include_path = os.path.join(lxml_path, 'includes')
includes = [include_path, lxml_path]
for name in os.listdir(include_path):
path = os.path.join(include_path, name)
if os.path.isdir(path):
includes.append(path)
return includes
這是lxml的__init__.py
文件(用於解析html,xml數據的python庫)。 您可以在具有子模塊的任何python庫下引用任何__init__.py
文件。 ex(os,sys) 。 在這里我提到了lxml,因為我覺得你很容易理解。 您甚至可以檢查其他庫/包下的__init__.py
文件。 每個人都有自己的方式來定義子模塊的路徑。
如果您嘗試導入目錄外的模塊。 然后,您必須導出模塊路徑,以便其他模塊可以將它們找到環境變量中。 這可以通過將基礎目錄的絕對路徑附加到PYTHONPATH或PATH來直接完成。
要了解更多:
因此,要解決您的問題,請在proj-dir下的__init__.py
文件中包含所有子模塊的路徑,並將/ absolute / path /添加到/ proj-dir或者添加到PYTHONPATH
或PATH
。
希望答案能解釋您對__init__.py
使用並解決您的問題。
在Linux上,您只需將src
目錄的父文件夾的路徑添加到~/.local/lib/python3.6/site-packages/my_modules.pth
。 請參閱使用.pth文件 。 然后,您可以從系統中的任何位置導入src
模塊。
NB1:用你想要使用的任何Python版本替換python3.6
。
NB2:如果你使用Python2.7(不知道其他版本),你需要在src/
和src/utils
創建__init__.py
(空)文件。
NB3:任何名稱.pth
文件都可以用於my_modules.pth
。
是的,您只能從已安裝的軟件包或工作目錄或子目錄中的文件導入代碼。
我看到它的方式,你的問題將得到解決,如果你將安裝你的模塊或包,如安裝和安裝,然后導入(numpy,xml,json等)
我還有一個我經常在我的所有項目中使用的軟件包, ulitilies ,我知道這對導入很痛苦。
這里有一個關於如何打包python應用程序以使其可以進行pip安裝的描述: https : //marthall.github.io/blog/how-to-package-a-python-app/
導航到python安裝文件夾
導航到lib
導航到站點包
創建一個名為any_thing_you_want.pth
的新文件
使用您喜歡的文本編輯器在該文件中鍵入.../src/utils/helpers.py
注意: scr/utils/helpers.py
之前的省略號看起來像: C:/Users/blahblahblah/python_folders/scr...
< - 你需要這個!
這是一種廉價的出路,但它保持代碼清潔,並且是最不復雜的。 缺點是,對於您的模塊所在的每個文件夾,example.pth都需要它們。 好處:與Windows一起使用Windows 10
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.