简体   繁体   English

如何将 setup.py 替换为 pyproject.toml 以获得本机 C 构建依赖项?

[英]How to replace setup.py with a pyproject.toml for a native C build dependency?

I came across this little project for creating a C-compiled version of the Black-Scholes function to be used in python.我遇到了 这个小项目,用于创建Black-Scholes function 的 C 编译版本,以用于 python。

Although the example code seem to have been published in July this year, it seem that the use setup.py type of build has been deprecated beyond legacy builds.尽管示例代码似乎已于今年 7 月发布,但使用setup.py类型的构建似乎已被弃用,超出了遗留构建。 Any compilation fails, first complaining about missing MS C++ 14 compiler (which is not true), then further investigation, seem to indicate that setup.py can no longer be used.任何编译失败,首先抱怨缺少MS C++ 14编译器(这不是真的),然后进一步调查,似乎表明无法再使用 setup.py。

Q: How can I convert the setup.py to a valid pyproject.toml file?问:如何将setup.py转换为有效的pyproject.toml文件?

from setuptools import setup, Extension

ext = Extension('bs', sources=['black_scholes/bs.c'])

setup(
    name="black_scholes",
    version="0.0.1",
    description="European Options Pricing Library",
    packages=['black_scholes'],
    ext_modules=[ext]
)

From the somewhat ambiguous website (above), I created the following tree structure.从有点模棱两可的网站(上图),我创建了以下树结构。

$ tree -L 3 ./
./
├── black_scholes
│   ├── black_scholes
│   │   ├── Makefile
│   │   ├── __init__.py
│   │   └── bs.c
│   ├── pyproject.toml
│   └── setup.py
├── README.md
└── bs_test.py

Possibly relevant questions:可能相关的问题:

After having wasted 2 days on trying to circumvent the required Visual Studio C++ Build tools requirements, the only unfortunate option that would work, was to submit to the >7GB download in order to get my 20 line C-function to compile and install nicely on Py3.10 .在浪费了 2 天时间试图绕过所需的Visual Studio C++ Build tools要求之后,唯一可行的不幸选项是提交>7GB下载,以便让我的 20 行 C 函数能够很好地编译和安装Py3.10 (Follow this .) (按照这个。)

Using an external _custom_build.py使用外部_custom_build.py

Here are the files that worked:以下是有效的文件:

# setup.py
from setuptools import setup, Extension

ext = Extension('bs', sources=['black_scholes/bs.c'])

setup(
    name="black_scholes",
    version="0.0.1",
    description="European Options Pricing Library",
    packages=['black_scholes'],
    ext_modules=[ext]
)

Then for the pyproject.toml :然后对于pyproject.toml

# pyproject.toml
[build-system]
requires = ["setuptools>=61.0", "cython"]
build-backend = "setuptools.build_meta"

[project]
name        = "black_scholes"
description = "European Options Pricing Library"
version     = "0.0.1"
readme      = "README.md"
requires-python = ">=3.7"
authors = [
  { name="Example Author", email="author@example.com" },
]
classifiers = [
    "Programming Language :: Python :: 3",
    "License :: OSI Approved :: MIT License",
    "Operating System :: OS Independent",
]
keywords = ["quant", "portfolio"]

[project.urls]
"Homepage" = "https://pyquantnews.com/how-to-45x-python-performance-with-c/"

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

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

This is using an external build file called _custom_build.py , as suggested from the SO link above.这是使用一个名为_custom_build.py的外部构建文件,正如上面 SO 链接所建议的那样。

# _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(
                "bs",
                sources=["black_scholes/bs.c"],
                extra_compile_args=["-std=c17", "-lm", "-Wl", "-c", "-fPIC"],
            )
        )

However, it seem that the extra_compile_args are completely ignored...但是,似乎完全忽略了extra_compile_args ...

It would have been great if someone could come up with an alternative solution to build using smaller compiler, like MinGW or so.如果有人能想出一个替代解决方案来使用较小的编译器(如MinGW等)进行构建,那就太好了。

The final tree should look like this:最终的树应该是这样的:

$ tree -L 3
.
├── black_scholes
│   ├── black_scholes
│   │   ├── Makefile
│   │   └── bs.c
│   ├── .gitignore
│   ├── README.md
│   ├── __init__.py
│   ├── _custom_build.py
│   ├── pyproject.toml
│   └── setup.py
└── bs_test.py

Using a src build with setup.py & pyproject.toml使用带有setup.pypyproject.tomlsrc构建

UPDATE: 2022-11-14更新:2022-11-14

The above procedure turned out to be very messy and also gave different results depending on how you used pip install .上面的过程变得非常混乱,并且根据您使用pip install的方式也给出了不同的结果。 In the end I completely changed the flat folder structure to use a src based structure.最后我完全改变了平面文件夹结构以使用基于src的结构。 The working project now look like this:工作项目现在看起来像这样:

# tree -L 3
.
├── docs
├── examples
│   └── fbs_test.py
├── src
│   ├── black_scholes
│   │   └── __init__.py
│   └── lib
│       ├── Makefile
│       └── fbs.c
├── .gitignore
├── LICENSE.md
├── README.md
├── clean.sh
├── pyproject.toml
└── setup.py

and the content of the files are like this:文件的内容是这样的:

# setup.py

from setuptools import setup, find_packages, Extension

ext = Extension(
    name                = 'black_scholes.fbs',          # 'mypackage.mymodule'
    sources             = ['src/lib/fbs.c'],            # list of source files (to compile)
    include_dirs        = ['src/lib'],                  # list of directories to search for C/C++ header files (in Unix form for portability)
    py_limited_api      = True                          # opt-in flag for the usage of Python's limited API <python:c-api/stable>.
)

setup_args = dict(
    packages        = find_packages(where="src"),       # list 
    package_dir     = {"": "src"},                      # mapping
    ext_modules     = [ext],                            # list
    scripts         = ["examples/fbs_test.py"]          # list
)

setup(**setup_args)

and

# pyproject.toml

[build-system]
requires        = ['setuptools>=61.0']                  # 'cython'
build-backend   = 'setuptools.build_meta'   

[project]
name            = 'black_scholes'

# ...

[tool.setuptools]
package-dir = {"" = "src"}
#py-modules = ["_custom_build"]

[tool.setuptools.packages.find]
where = ["src"]

Here it is very important that the package name coincide with the src/black_scholes directory name.在这里,package 名称与src/black_scholes目录名称一致非常重要 If not you will have all sorts of very weird run-time errors even after the package has compiled and installed.否则,即使在 package 已编译和安装后,您也会遇到各种非常奇怪的运行时错误。

暂无
暂无

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

相关问题 如何构建符合 PEP 517 的 C 扩展,即使用 pyproject.toml 而不是 setup.py? - How to build a C extension in keeping with PEP 517, i.e. with pyproject.toml instead of setup.py? 关于 pyproject.toml 与 setup.py 的问题 - Questions on pyproject.toml vs setup.py conda-build 错误:目录 &#39;.&#39; 不可安装。 未找到“setup.py”和“pyproject.toml” - conda-build error: Directory '.' is not installable. Neither 'setup.py' nor 'pyproject.toml' found 从 setup.py 迁移到 pyproject.toml:如何指定 package 名称? - Migration from setup.py to pyproject.toml: how to specify package name? 如何从 setup.py 中读取来自 pyproject.toml 的项目依赖项,以避免在两个文件中重复信息? - How do I read project dependencies from pyproject.toml from my setup.py, to avoid duplicating the information in both files? Heroku 部署失败 | 既没有找到“setup.py”也没有找到“pyproject.toml”。 有谁知道如何解决这一问题? - Heroku fails to deploy | neither 'setup.py' nor 'pyproject.toml' found. Does anyone know how to fix this? setuptools pyproject.toml 相当于`python setup.py clean --all` - setuptools pyproject.toml equivalent to `python setup.py clean --all` 目录 '。' 不可安装。 未找到“setup.py”和“pyproject.toml” - Directory '.' is not installable. Neither 'setup.py' nor 'pyproject.toml' found 错误:目录不可安装。 “setup.py”和“pyproject.toml”都不是 - ERROR: Directory is not installable. Neither 'setup.py' nor 'pyproject.toml' 如何使用 pyproject.toml 构建万能轮 - How to build a universal wheel with pyproject.toml
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM