当前位置: 首页 > 知识库问答 >
问题:

如何根据PEP 517(即pyproject)构建C扩展。toml而不是setup.py?

年高洁
2023-03-14

我想为CPython构建一个C扩展。我传统上可以使用<code>设置来完成。py文件。然而,出于PEP517中提到的原因,我更喜欢使用<code>pyproject.toml</code>的声明性方法。我知道setuptools是唯一可以在所有相关平台上构建C扩展的构建后端。事实上,除了过时的distutils之外,我还不知道有任何后端能够构建C扩展。

在此背景下,常见的<code>设置。py将如下所示:

from setuptools import setup, Extension
kwargs = dict(
    name='mypackage',
    # more metadata
    ext_modules=[
        Extension('mypackage.mymodule', ['lib/mymodule.c',
                                         'lib/mypackage.c',
                                         'lib/myalloc.c'],
                  include_dirs=['lib'],
                  py_limited_api=True)])

setup(**kwargs)

现在的挑战是将上述内容放入< code>pyproject.toml和< code>setup.cfg中。

setup工具文档建议pyproject.toml如下所示:

[build-system]
requires = [
    "setuptools >=52.0",
        'wheel >= 0.36']
build-backend = "setuptools.build_meta"

看见

  • https://setuptools.readthedocs.io/en/latest/build_meta.html和
  • https://setuptools.readthedocs.io/en/latest/userguide/declarative_config.html#declarative-配置

此外,实际的元数据应该放入< code>setup.cfg中。但是,我还没有找到任何关于如何将< code>ext_modules kwarg,尤其是< code>Extension()调用,翻译成< code>setup.cfg语法的解释。

共有2个答案

萧宏远
2023-03-14

下面是一个黑客,可用于使用 pyproject.toml 构建 ext,而无需依赖 setup.py

pyproject.toml

[tool.setuptools]
py-modules = ["_custom_build"]

[tool.setuptools.cmdclass]
build_py = "_custom_build.build_py"

_custom_build.py

from setuptools import Extension
from setuptools.command.build_py import build_py as _build_py

class build_py(_build_py):
    def run(self):
        self.run_command("build_ext")
        return super().run()

    def initialize_options(self):
        super().initialize_options()
        if self.distribution.ext_modules == None:
            self.distribution.ext_modules = []

        self.distribution.ext_modules.append(
            Extension(
                "termial_random.random",
                sources=["termial_random/random.c"],
                extra_compile_args=["-std=c17", "-lm"],
            )
        )
祁刚毅
2023-03-14

严格来说,< code>pyproject.toml并不是要取代< code>setup.py,而是要确保在仍然需要的情况下正确执行它(参见PEP

如果存在构建后端密钥,则优先,并且源代码树遵循指定后端的格式和约定(因此,除非后端需要,否则不需要 setup.py)。项目可能仍希望包含与不使用此规范的工具兼容的 setup.py

虽然setuptools计划将所有内容从脚本移动到配置文件中,但这并不总是可能的:

有两种类型的元数据:静态和动态。

  • 静态元数据(setup.cfg):保证每次都是一样的,这样更简单,更容易阅读,并且避免了许多常见的错误,比如编码错误。
  • 动态元数据(setup.py):可能是非确定性的。任何动态的或在安装时确定的项目,以及扩展模块或setuptools的扩展,都需要进入setup.py

静态元数据应该是首选,而动态元数据应该仅在绝对必要时作为一个出口使用。

事实上,<code>setuptools</code>仍将使用虚构的<code>设置。py(如果不存在)。

注意:自版本

话虽如此,如果你想尽可能多地坚持静态方式,你可以将所有内容移动到pyproject.toml文件中,其余的暂时保留在 setup.py

[build-system]
requires = ["setuptools>=61"]
build-backend = "setuptools.build_meta"

[project]
name = "mypackage"
# more metadata
from setuptools import setup, Extension

setup_args = dict(
    ext_modules = [
        Extension(
            'mypackage.mymodule',
            ['lib/mymodule.c', 'lib/mypackage.c', 'lib/myalloc.c'],
            include_dirs = ['lib'],
            py_limited_api = True
        )
    ]
)
setup(**setup_args)
 类似资料:
  • 问题内容: 我有一个C扩展模块,很高兴分发内置的二进制文件。SetupTools使得在OS X和GNU / Linux上构建扩展模块变得很容易,因为那些OS随GCC一起提供,但是我不知道如何在Windows中进行。 我需要购买Visual Studio的副本,还是可以使用Visual Studio Express?我可以只使用Cygwin或MinGW吗? 问题答案: 您可以同时使用MinGW和VC

  • 我有一个proto,它有一条包含扩展名的消息 我有另一个proto,它有扩展(只显示下面的一个扩展) 通过protobuf代码,我能够获得MsgB的描述符和FileDescriptor,并从中检索FieldDescriptor类型的扩展名“MsgB”。我通过protobuf代码查找扩展,而不是使用MsgB协议生成的代码,因为我试图迭代所有扩展消息,而不是将每个消息硬编码为可变扩展。(我理解Muta

  • 作者:陈希章 发表于 2018年4月7日 前言 此前我有一篇 文章 讲解了Microsoft Graph的一种数据扩展技术—— 开发扩展(Open Extensions),它可以实现在支持的对象(例如用户,组等)上面附加任意的数据。但开放扩展的问题在于,它是基于某个具体对象的,你无法确定两个对象是否具有同样的扩展(即便属性名一样,但也可能其包含的数据完全不同)。如果我们需要对一类对象进行统一的扩展

  • 问题内容: 我想用Java解决带有多个线程的数学问题。我的数学问题可以分为多个工作单元,我想通过几个线程来解决。 我不希望有固定数量的线程在工作,而是与CPU核心数量匹配的线程数量。我的问题是,为此我在互联网上找不到简单的教程。我发现的只是带有固定线程的示例。 如何才能做到这一点?你能提供例子吗? 问题答案: 你可以通过使用静态运行时方法,确定提供给Java虚拟机的进程数availableProc

  • 问题内容: 我在python代码中发现了瓶颈,并与psycho等打交道。然后决定编写ac / c ++扩展以提高性能。 借助swig,您几乎不需要关心参数等。一切正常。 现在我的问题是:swig创建了一个很大的py文件,该文件在调用实际的.pyd或.so代码之前会执行很多“检查”和“ PySwigObject”。 你们中的任何人是否有经验,如果您手动编写此文件或让wig来做,是否可以获得更多性能。