简体   繁体   English

用可执行文件打包Python库

[英]Packaging a Python library with an executable

I just finished a module and want to package it. 我刚刚完成一个模块,并希望将其打包。 I've read the documentation and this question packaging a python application but I am not sure about how to proceed when I don't have a package to import but a script to launch instead. 我已经阅读了文档和打包python应用程序的问题,但是当我没有要导入的包而是要启动的脚本时,我不确定如何继续。

The project looks like that: 该项目如下所示:

Project/
|-- README
|-- requirement.txt
|-- driver.py
|-- run.py
|-- module_1
|   |-- __init__.py
|   |-- class_1.py
|   |-- class_2.py
|-- module 2
|-- |-- __init__.py
|-- |-- class_1.py
|-- |-- class_2.py

In order to launch the tool I do: 为了启动该工具,我要做的是:

python run.py arg1 --option arg2

driver.py imports all other modules and defines a Driver class and some functions. driver.py导入所有其他模块,并定义一个Driver类和一些函数。 run.py imports driver.py , parse arguments, setups the logger and calls the function one after the others to do the job. run.py导入driver.py ,解析参数,设置记录器并driver.py调用该函数以完成工作。

I'm not sure about the configuration of setup.py , also do I need a global __init__.py at the root? 我不确定setup.py的配置,也需要在根目录下使用全局__init__.py吗? From what I've understand, I will only be able to do import Project not to launch the script run.py with its arguments. 据我了解,我将只能import Project而不启动带有参数的脚本run.py

From other readings, maybe I should try to tell that Driver.py is the package and use the entry_points option of setup() . 从其他读物来看,也许我应该尝试说出Driver.py是软件包,并使用setup()entry_points选项。 But I don't understand how to do all of it properly. 但是我不知道如何正确地完成所有这些工作。

Thank you for your kind help! 谢谢你的热心帮助!

Generally, you only distribute python packages as modules when the entire project fits in a single module file. 通常,仅当整个项目适合单个模块文件时,才将python软件包作为模块分发。 If your project is more complex than that, it's usually best to structure your project as a package with an __init__.py file. 如果您的项目比这更复杂,通常最好将项目构造为带有__init__.py文件的程序包。 Here is what your project would look like converted to a package 这是您的项目转换成包后的样子

Project/
|-- README
|-- requirement.txt
|-- setup.py
|-- scripts/
|   |-- driver.py
|-- driver/
|   |-- __init__.py
|   |-- module_1
|   |   |-- __init__.py
|   |   |-- class_1.py
|   |   |-- class_2.py
|   |-- module_2
|   |-- |-- __init__.py
|   |-- |-- class_1.py
|   |-- |-- class_2.py

I renamed your run.py to scripts/driver.py and the code you previously had in driver.py is now driver/__init__.py . 我将您的run.py重命名为scripts/driver.py ,以前在driver.py拥有的代码现在为driver/__init__.py

Your setup.py should look like this 您的setup.py应该看起来像这样

from setuptools import setup. find_packages

setup(
    name='driver',
    version='1.0',
    packages=find_packages(),
    scripts=['scripts/driver.py'],
)

This will copy scripts/driver.py to the python Scripts directory. 这会将scripts/driver.py复制到python Scripts目录。 I renamed run.py to driver.py since run is pretty generic and you want your script names to be unique since all python packages share the same scripts location. 我改名run.pydriver.py因为run是非常通用的,你希望你的脚本名称是唯一的,因为所有Python包共享相同的脚本的位置。

Alternatively, you could use the console_scripts entry point. 或者,您可以使用console_scripts入口点。 In this case, you wouldn't have a separate scripts/driver.py script. 在这种情况下,您将没有单独的scripts/driver.py脚本。 Instead, you would just have a function inside your package. 取而代之的是,您的包中只有一个函数。 In this case, you could move all the code from scripts/driver.py into driver/command_line.py and put it inside a function called main() . 在这种情况下,您可以将所有代码从scripts/driver.py移到driver/command_line.py并将其放入一个名为main()的函数中。 Then change your setup.py to this 然后将您的setup.py更改为此

setup(
    name='driver',
    version='1.0',
    packages=find_packages(),
    entry_points = {
        'console_scripts': ['driver=driver.command_line:main'],
    }
)

Also, you should read this docs page on python packaging . 另外,您应该阅读有关python Packaging的此文档页面 It covers the basics and a lot of the common use cases. 它涵盖了基础知识和许多常见用例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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