[英]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 .) (按照这个。)
_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
src
build with setup.py
& pyproject.toml
setup.py
和pyproject.toml
的src
构建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.