在浪费了两天时间试图规避所需的要求之后视觉工作室C++ Build tools
要求,唯一可行的不幸选择是提交给>7GB
下载以便让我的 20 行 C 函数能够很好地编译和安装Py3.10
。 (跟随this.)
使用外部_custom_build.py
以下是有效的文件:
# 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]
)
那么对于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="[email protected]" },
]
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"
这是使用名为的外部构建文件_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"],
)
)
然而,似乎extra_compile_args
完全被忽略了...
如果有人能提出使用较小的编译器构建的替代解决方案,那就太好了,例如MinGW
or so.
最终的树应该是这样的:
$ 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
构建与setup.py
& pyproject.toml
更新:2022-11-14
上面的过程非常混乱,而且根据你的使用方式也给出了不同的结果pip install
。最后我完全改变了平面文件夹结构以使用src
为基础的结构。现在的工作项目如下所示:
# 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
文件的内容是这样的:
# 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"]
这里是很重要包名称与src/black_scholes
目录名称。如果没有,即使在编译和安装包之后,您也会遇到各种非常奇怪的运行时错误。