微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用相同的 setup.py 来开发和安装非 cythonized 和 cythonized 包?

如何解决使用相同的 setup.py 来开发和安装非 cythonized 和 cythonized 包?

Give 是一个(一组)python3 包,它们将被部署在不同的场景中,无论是 cythonized 还是作为原始脚本;源代码是纯 python3代码。如果可能,我最好使用相同的 setup.py

用例 就地 包含 .py 模块 cythonized .so 模块
1。发展pip3 install -e . 是的 是的
2. “未优化”安装 pip3 install . 是的
3. cythonized 安装 pip3 install . --install-option="cythonize" 否(除了__init__.py 是的
4.构建(二进制)轮 python3 setup.py bdist_wheel 否(除了__init__.py 是的

到目前为止,我成功地构建一个二进制分发轮,只包含 cythonized .so 共享库,没有原始 .py 模块文件,遵循 Package only binary compiled .so files of a python library compiled with Cython 。这涵盖了用例 #4,并由类 build_py 处理。

然而,我也会涵盖 #1、#2 和 #3; #3 可以通过单独构建 bdist_wheel 然后安装它来更好地解决,否则不可能在一个步骤中完成。

# https://stackoverflow.com/a/56043918
from setuptools.command.build_py import build_py as build_py_orig
try:
    from Cython.Build import cythonize
except:
    cythonize = None

from setuptools.command.install import install as install_orig

# https://stackoverflow.com/a/56043918
extensions = [
    Extension('spam.*',['spam/**/*.py'],extra_compile_args=["-O3","-Wall"]),]

cython_excludes = ['spam/**/__init__.py']

def not_cythonized(tup):
    (package,module,filepath) = tup
    return any(
        fnmatch.fnmatchcase(filepath,pat=pattern) for pattern in cython_excludes
    ) or not any(
        fnmatch.fnmatchcase(filepath,pat=pattern)
        for ext in extensions
        for pattern in ext.sources
    )


class build_py(build_py_orig):
    def find_modules(self):
        modules = super().find_modules()
        return list(filter(not_cythonized,modules))

    def find_package_modules(self,package,package_dir):
        modules = super().find_package_modules(package,package_dir)
        return list(filter(not_cythonized,modules))


class install(install_orig):
    def finalize_options(self):
        super().finalize_options()
        self.distribution.ext_modules = None

setup(
    name='spam',packages=find_packages(),ext_modules=cythonize(
        extensions,exclude=cython_excludes,compiler_directives={
            "language_level": 3,"always_allow_keywords": True,},build_dir="build",# needs to be explicitly set,otherwise pollutes package sources
    ) if cythonize is not None else [],cmdclass={
        'build_py': build_py,'install': install,include_package_data=True,install_requires=[...]
)

在这里面临的问题:

  1. 对于用例 #1 和 #2,我不想进行 cythonize,因此不应指定/设置 ext_modules=

    1. 在这种情况下,处理 ext_modules= 的明智方法是什么?我发现在调用 install 之前, 很难检测到请求的操作 (install -e,develop,setup()),所以最好继承并覆盖 installdevelop 类?

    2. 如果是后者,是否可以并允许清除 ext_modules 以及如何避免过早评估 cythonize(...)

  2. 在使用上述代码的用例 #2 中,pip3 决定构建一个包含 .so 的鸡蛋。这可能是因为 cythonize(...) 在任何情况下都被评估了吗?我可以避免构建 egg 吗,或者如何防止 Egg 构建过程包含共享库?

  3. 这当前包括代码(我不想包含)以及 cythonized 模块:如何防止 install 类安装大多数源模块,但是安装__init__.py

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。