問題描述
我嘗試閱讀有關同級導入的問題,甚至包文檔,但我還沒有找到答案.
I've tried reading through questions about sibling imports and even the package documentation, but I've yet to find an answer.
結構如下:
├── LICENSE.md
├── README.md
├── api
│?? ├── __init__.py
│?? ├── api.py
│?? └── api_key.py
├── examples
│?? ├── __init__.py
│?? ├── example_one.py
│?? └── example_two.py
└── tests
│?? ├── __init__.py
│?? └── test_one.py
examples
和 tests
目錄下的腳本如何從api
模塊并從命令行運行?
How can the scripts in the examples
and tests
directories import from the
api
module and be run from the commandline?
另外,我想避免對每個文件進行丑陋的 sys.path.insert
hack.一定這可以在 Python 中完成,對吧?
Also, I'd like to avoid the ugly sys.path.insert
hack for every file. Surely
this can be done in Python, right?
推薦答案
七年后
自從我在下面寫了答案后,修改 sys.path
仍然是一個快速而骯臟的技巧,適用于私有腳本,但已經有了一些改進
Seven years after
Since I wrote the answer below, modifying sys.path
is still a quick-and-dirty trick that works well for private scripts, but there has been several improvements
- 盡管我建議使用 pip這樣做而不是直接使用 setuptools(并使用
- 使用
-m
標志并作為包運行也可以(但會轉如果你想把你的工作目錄轉換成一個可安裝的包,那就有點尷尬了). - 對于測試,具體來說,pytest 能夠在這種情況下找到 api 包并處理
sys.path
為您提供的技巧
setup.cfg
來存儲元數據)- Installing the package (in a virtualenv or not) will give you what you want, though I would suggest using pip to do it rather than using setuptools directly (and using
setup.cfg
to store the metadata) - Using the
-m
flag and running as a package works too (but will turn out a bit awkward if you want to convert your working directory into an installable package). - For the tests, specifically, pytest is able to find the api package in this situation and takes care of the
sys.path
hacks for you
所以這真的取決于你想做什么.但是,在您的情況下,由于您的目標似乎是在某個時候制作適當的軟件包,因此通過 pip -e
安裝可能是您最好的選擇,即使它還不完美.
So it really depends on what you want to do. In your case, though, since it seems that your goal is to make a proper package at some point, installing through pip -e
is probably your best bet, even if it is not perfect yet.
正如在其他地方已經說過的,可怕的事實是,你必須做一些丑陋的 hack 才能允許從 __main__
模塊導入兄弟模塊或父包.PEP 366 中詳細介紹了該問題.PEP 3122 試圖以更合理的方式處理導入,但 Guido 拒絕了它一個帳號
As already stated elsewhere, the awful truth is that you have to do ugly hacks to allow imports from siblings modules or parents package from a __main__
module. The issue is detailed in PEP 366. PEP 3122 attempted to handle imports in a more rational way but Guido has rejected it one the account of
唯一的用例似乎是運行發生的腳本生活在一個模塊的目錄中,我一直將其視為一個反模式.
The only use case seems to be running scripts that happen to be living inside a module's directory, which I've always seen as an antipattern.
(這里)
不過,我經常使用這種模式
Though, I use this pattern on a regular basis with
# Ugly hack to allow absolute import from the root folder
# whatever its name is. Please forgive the heresy.
if __name__ == "__main__" and __package__ is None:
from sys import path
from os.path import dirname as dir
path.append(dir(path[0]))
__package__ = "examples"
import api
這里 path[0]
是您正在運行的腳本的父文件夾,而 dir(path[0])
是您的頂級文件夾.
Here path[0]
is your running script's parent folder and dir(path[0])
your top level folder.
盡管如此,我仍然無法使用相對導入,但它確實允許從頂層(在您的示例 api
的父文件夾中)進行絕對導入.
I have still not been able to use relative imports with this, though, but it does allow absolute imports from the top level (in your example api
's parent folder).
這篇關于兄弟包導入的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!