2015-05-04 16 views
5

Moje projekty Pythona 3 często używają cythonu.Cython: pyximport: włączanie profilowania w pyximport.install

W wdrożenia produkcyjnego, używam skryptu build, który, między innymi, wyłącza profilowanie:

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, 
    ) 
) 

w rozwoju, używam pyximport. Aby odróżnić te dwa konteksty, testuję, czy użytkownik "produkcyjny" jest używany w pliku najwyższego poziomu projektu __init__.py projektu. Jeśli nie jest to produkcja, używam pyximport; pyximport.install, tak że staje się całkowicie przezroczysty:

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, 
    ) 

ja chciałby włączyć profilowanie dla wszystkich Cython plików jednocześnie w środowisku programistycznym. Próbowałem dodać argument profile=True do instrukcji piximport.install, ale to nie działa.

Jak mogę kontynuować?

Niektóre dodatkowe komentarze:

  • które chciałbym uniknąć pchania Profile=True we wszystkich kodów źródłowych jednocześnie w rozwoju i ich usunięcie przed popełnienia ...

  • Korzystanie .pyxbld plików nie jest opcja dla mnie, ponieważ mam 46 plików pyx i planuję mieć o wiele więcej ... Chyba że istnieje sposób na ustawienie tylko jednego pliku obsługującego wszystkie pyx, tak jak zrobiłem dla skryptu kompilacji, ale nie znalazłem sposobu.

Dzięki za pomoc.

Odpowiedz

2

Wymaga to owijanie jednym z wewnętrznych funkcji pyximport, ale można to zrobić:

# 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() 

Należy pamiętać, że to nie będzie przymusowo skompilować moduły niezmienione z nowymi opcjami; będziesz musiał touch tych plików, aby uruchomić kompilację z nową konfiguracją.

2

Oto pozornie nieudokumentowane sposób przekazać dyrektyw:

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

znalazłem nazwę cython_directives w Cython/distutils/build_ext.py.