【问题标题】:Confused about packing python projects对打包python项目感到困惑
【发布时间】:2018-04-14 01:17:59
【问题描述】:

我用 Python 编码已经很长时间了,但从来没有真正尝试过打包一段代码以便我可以分享它。我开始阅读 https://python-packaging.readthedocs.io/en/latest/

我从最简单的情况开始,假设我想共享一个名为“clipper”的模块,唯一重要的是一个名为 Clipper 的类。看来如果我使用 setuptools 我应该在某处创建文件夹

clipper/clipper

在内部剪辑器中,放置一个文件__init__.py

与类 Clipper 的定义。到目前为止,一切都很好。理论上,安装包后,类的使用方式是:

import clipper
cl = clipper.Clipper()

我的问题是,我假设在开发和安装之前,相同的代码应该可以工作。我的意思是,前面的代码应该创建对象的一个​​实例。但这将如何运作?我应该如何设置 PYTHONPATH 以便之前的导入真正起作用?

也许我真的错了,我认为打包比编码更容易,但我花了一些时间,但我不明白。请帮忙?

【问题讨论】:

  • 您有兴趣将其转换为可执行文件吗?您的目标平台是什么?
  • 不,我不需要可执行文件。平台:目前是Windows上的Python 3.5。
  • 我不想为自己做广告,但我已经按照您的意愿设置了一个项目。您可能会在我的 setup.py 文件中找到一些有用的东西。我使用 virtualenv 在开发过程中自动设置 PYTHONPATH。当我使用pip install 从 pypi 下载包时,我可以轻松导入模块。 github.com/byxor/limp

标签: python package setuptools


【解决方案1】:

与其修改您的 Python 路径,不如将打包的模块安装为可编辑版本,您的环境将为您处理此问题。当您将其作为可编辑版本运行时,您将能够更改本地开发实例上的代码。

例如,假设您有 Pip,您可以在第一个“clipper”文件夹(与您在打包过程中创建的 setup.py 文件相同的文件夹)中运行以下命令:

pip install -e .
  • -e 表示可编辑
  • . 表示安装位于当前文件夹中的包。

更多详情请参阅 2015 年的 SO 答案:"pip install --editable ./" vs "python setup.py develop"

【讨论】:

  • 谢谢,这正是我所需要的!我会好好看看的。
【解决方案2】:

你的目录树看起来有点像这样:

~/clipper/
    setup.py
    clipper/
        __init__.py
        clipper.py

setup.py 文件包含告诉 Python 如何“解析”你的包的信息。项目名称、版本和要包含的包等内容都在此处定义。对于您的示例,setup.py 可能如下所示:

from distutils.core import setup

setup(
    name="Clipper",
    # A name for your package, typically your project name
    description="My first package",
    # A short description
    version="1.0.0",
    # A version specification
    packages=["clipper"]
    # A list of packages to include
)

clipper 内,clipper.py 包含实际的Clipper 类:

class Clipper(object):
    def __init__(self):
        pass

    def foo(self):
        print("Invoked foo!")

__init__.py 是一种特殊类型的文件。它定义了与你的包交互的公共接口。通常,它imports 所有公共函数和类:

from .clipper import Clipper

最后,要将其转换为正确的包,请运行 python3 setup.py sdist。这将为您的包创建sdistribution,并允许您导入它1。现在让我们试试吧。导航回~/clipper/ 并启动 Python:

>>> from clipper import Clipper
>>> c = Clipper()
>>> c.foo()
Invoked foo!
>>>

下面是包目录的“真实”示例:

~/calculator/
    setup.py
    calculator/
        __init__.py
        add.py
        substract.py

setup.py

from distutils.core import setup

setup(
    name="Calculator",
    description="Calculate stuff!",
    version="1.0.0",
    packages=["calculator"]
)

__init__.py

from .add import *
from .substract import *

add.py

def add(a, b):
    """Return `a` + `b`."""
    return a + b

substract.py

def substract(a, b):
    """Return `a` - `b`."""
    return a - b

有关详细信息,请参阅Python tutorial on packaging

1您可能会收到一些关于缺少信息的警告,但您现在可以忽略它。

【讨论】:

  • 很好的例子,教程参考。
猜你喜欢
  • 2012-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-20
  • 2023-03-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多