[英]Need proper directory structure for python packages and guidelines on good API design
I am in the midst of releasing a python package, and am confused about every aspect of packaging. 我正在发布python软件包,并对包装的各个方面感到困惑。
To start, my directory structure is as follows: 首先,我的目录结构如下:
SamplePackage/
- setup.py
- README.rst
- LICENSE.rst
- sampledir/
-__init__.py
-sample.py
-utils.py
currently __init__
and setup
are unpopulated. 当前
__init__
和setup
尚未填充。 sample.py
is the file that any user of the package would want to import. sample.py
是软件包的任何用户都想要导入的文件。 It contains the api in the form of different functions: foo1
, foo2
. 它包含具有不同功能形式的api:
foo1
, foo2
。
utils.py
contains helper fictions for smaple.py
. utils.py
包含帮手小说smaple.py
。 The latter contains a statement import utils
后者包含一条语句
import utils
Any scripts placed under the sampledir
directory can easily import sample
and use the fictions as sample.foo1()
. 放在
sampledir
目录下的任何脚本都可以轻松import sample
并将小说用作sample.foo1()
。 Stepping out of this directory, I can call import sampledir
, but not import sample
, which is expected. 退出该目录,我可以调用
import sampledir
,但不能调用import sample
,这是预期的。 So I need to do from sampledir import sample
. 所以我需要
from sampledir import sample
。 This results in an error on the import utils
line in sample.py
这导致
sample.py
的import utils
行出现错误
ImportError: No module named 'utils'
In some places I have seen import .utils
for files in the same directory. 在某些地方,我看到了在同一目录中
import .utils
文件的信息。 But when I try that, it results in a syntax error. 但是,当我尝试这样做时,会导致语法错误。
Why can I not import sample.py
from outside sampledir? 为什么我不能从sampledir外部导入
sample.py
?
Also, what directory structure would allow users who have installed the package to simply be able to call import sample
followed by sample.foo1()
, and not have to do from sampledir import sample
or import sampeldir.sample
. 同样,什么样的目录结构将允许已安装软件包的用户能够简单地调用
import sample
然后调用sample.foo1()
,而不必from sampledir import sample
或import sampeldir.sample
。 For example, in using the HTTP library requests
, one simply has to import it and call requests.get(url)
. 例如,在使用HTTP库
requests
,只需将其导入并调用requests.get(url)
。 requests.requests.get('url')
is not required, like it is in urllib
. 像在
urllib
一样,不需要urllib
requests.requests.get('url')
。 What is the correct directory naming and arrangement to achieve that, if I want the package to be named sample
? 如果我想将该包命名为
sample
,那么实现该目的的正确目录命名和安排是什么?
First of all, I thing you've misunderstood what is difference between package and project. 首先,我想你误解了包和项目之间的区别。 You directory structure should be something like this
您的目录结构应该是这样的
arbitrary_name_of_project/
- setup.py
- README.rst
- LICENSE.rst
- package_name/
-__init__.py
-sample.py
-utils.py
Python package is "marked" by a presence of file __init__.py
. 存在文件
__init__.py
来“标记” Python软件包。 Python search on his PYTHONPATH
and seeks for all directories with file __init__.py
(simply put, it's actually much more complicated). Python在他的
PYTHONPATH
上搜索,并寻找文件__init__.py
所有目录(简单地说,实际上要复杂得多)。 Those are packages that you can import during run-time. 这些是您可以在运行时导入的程序包。
In our case, only package_name
directory will be installed somewhere to PYTHONPATH
. 在我们的情况下,仅
package_name
目录将安装在PYTHONPATH
某个位置。 Therefore, once installed (via setup.py
and disutils
or setuptools
), you can type 因此,安装完成后(通过
setup.py
和disutils
或setuptools
),您可以输入
import package_name
Now, you can call arbitrary class or function or whatever from any module in this package like 现在,您可以从此包中的任何模块调用任意类或函数,或诸如此类
package_name.sample.func1()
If you want to avoid typing package_name.sample
in you call, you can place this line in __init__.py
如果要避免在调用中键入
package_name.sample
,可以将此行放在__init__.py
from .sample import func1
The function func1
will be then put in your global name space during "import time". 然后,在“导入时间”期间将函数
func1
放入您的全局名称空间。 This happens when import package_name
is executed in your program. 在程序中执行
import package_name
时,会发生这种情况。 This mystery can be resolved by the fact that __init__.py
file are executed every time package is imported. 可以通过每次导入包时都执行
__init__.py
文件这一事实来解决此问题。
It is sometimes necessary to spit the structure even more. 有时有必要吐更多的东西。 You can have "nested" packages (ie packages in package that you need to import).
您可以具有“嵌套”包(即,需要导入的包中的包)。 There are also namespace packages, where you can "spit" one package among more directories.
还有名称空间包,您可以在其中将一个包“吐”到更多目录中。 The world is diverse.
世界是多元化的。 :)
:)
Disclaimer 免责声明
I wrote that without testing the code I provided. 我写的是没有测试我提供的代码。 There might be small typos but I hope the story is more or less correct.
可能会有小的错别字,但我希望这个故事或多或少是正确的。 Please, correct me if I'm wrong.
请,如果我错了,请纠正我。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.