Cython:pyximport:在 pyximport.install 中启用分析

Posted

技术标签:

【中文标题】Cython:pyximport:在 pyximport.install 中启用分析【英文标题】:Cython: pyximport: enabling profiling in pyximport.install 【发布时间】:2015-05-04 10:49:30 【问题描述】:

我的 Python 3 项目经常使用 cython。

在生产部署中,我使用了一个构建脚本,其中包括禁用分析:

from distutils.core import setup
from Cython.Build import cythonize
import os

compiler_directives = 
    'language_level': 3,
    'optimize.use_switch': True,
    'profile': True,


setup(
    packages=["XXXXXX"],
    ext_modules=cythonize(
        module_list="**/*.pyx",
        compiler_directives=compiler_directives,
    )
)

在开发中,我使用的是 pyximport。为了区分这两种情况,我正在测试项目的***__init__.py 文件中是否正在使用“生产”用户。如果这不是生产,我使用pyximport; pyximport.install,使其变得完全透明:

if getpass.getuser != PRODUCTION_USER_NAME:
    import pyximport
    pyximport.install(
        pyximport=True,
        pyimport=False,
        build_dir=None,
        build_in_temp=True,
        setup_args=,
        reload_support=False,
        load_py_module_on_import_failure=False,
        inplace=False,
        language_level=3,
    )

我想在开发环境中启用所有 cython 文件的分析。我尝试将profile=True 参数添加到piximport.install 语句,但它不起作用。

我该如何继续?

一些额外的 cmets:

我想避免在开发过程中在所有源代码中推送Profile=True,并在提交之前将其删除...

使用.pyxbld 文件对我来说不是一个选项,因为我有 46 个 pyx 文件并计划拥有更多...除非有一种方法可以像我一样设置一个文件来支持所有 pyx构建脚本,但我没有找到方法。

感谢您的帮助。

【问题讨论】:

【参考方案1】:

它需要包装 pyximport 的内部函数之一,但这可以做到:

# Allow .pyx files to be seamlessly integrated via cython/pyximport with
# default compiler directives.
import functools
import pyximport.pyximport

# Hack pyximport to have default options for profiling and embedding signatures
# in docstrings.
# Anytime pyximport needs to build a file, it ends up calling
# pyximport.pyximport.get_distutils_extension.  This function returns an object
# which has a cython_directives attribute that may be set to a dictionary of
# compiler directives for cython.
_old_get_distutils_extension = pyximport.pyximport.get_distutils_extension
@functools.wraps(_old_get_distutils_extension)
def _get_distutils_extension_new(*args, **kwargs):
    extension_mod, setup_args = _old_get_distutils_extension(*args, **kwargs)

    if not hasattr(extension_mod, 'cython_directives'):
        extension_mod.cython_directives = 
    extension_mod.cython_directives.setdefault('embedsignature', True)
    extension_mod.cython_directives.setdefault('profile', True)
    return extension_mod, setup_args
pyximport.pyximport.get_distutils_extension = _get_distutils_extension_new
pyximport.install()

请注意,这不会强制使用新选项重新编译未更改的模块;您必须touch 这些文件才能触发使用新配置的编译。

【讨论】:

【参考方案2】:

这是一种显然没有记录的传递指令的方式:

pyximport.install(setup_args=
    'options': 
        'build_ext': 
            'cython_directives': 
                'language_level': 3,
                'optimize.use_switch': True,
                'profile': True,
            
        
    
)

我在 Cython/Distutils/build_ext.py 中找到了 cython_directives 名称。

【讨论】:

以上是关于Cython:pyximport:在 pyximport.install 中启用分析的主要内容,如果未能解决你的问题,请参考以下文章

使用 pyximport reload_support 重新加载 Cython 不起作用

什么是 pyximport,我应该如何使用它?

cx_Freeze 无法包含 Cython .pyx 模块

在 Cython 中使用 C++ STL 映射

在 C++ 中嵌入 Cython

在Cython中使用pyqt类(.pyx文件)