简体   繁体   English

需要适用于python软件包的正确目录结构以及有关良好API设计的准则

[英]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: foo1foo2

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.pyimport 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 sampleimport 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.pydisutilssetuptools ),您可以输入

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM