2017-01-21 2 views
2

파이썬 모듈을 파이썬으로 완벽하게 구현했습니다. (이식성을 이유로)setup.py에서 가능한 경우에만 cython 확장 옵션 컴파일

작은 부분의 구현이 cython 모듈에 복제되었습니다. 가능하면 성능을 개선하십시오.

모듈을 distutils과 함께 cython으로 만든 모듈을 설치하는 방법을 알고 있습니다. 그러나 컴퓨터에 컴파일러가 설치되어 있지 않으면 순수 파이썬 모드에서 모듈을 사용할 수있는 경우에도 설치가 실패합니다.

가능한 경우 .c 모듈을 컴파일하는 방법이 있습니까? 정상적으로 실패하고 컴파일 할 수없는 경우 설치하지 않고 설치 하시겠습니까?

답변

0

How should I structure a Python package that contains Cython code

이 관련 질문은 질문은 "이미 생성 된 C 코드"를 사이 썬에서 폴백하는 방법이있다. 비슷한 전략을 사용하여 .py 또는 .pyx 코드 중 설치할 코드를 선택할 수 있습니다.

+0

어떻게 적용되는지 모르겠습니다. 파이썬 모듈로 cython을 가져오고 가져 오기가 실패하면 C 모듈로 폴백합니다. 어떻게하면 파이썬에서 시스템 C 컴파일러를 가져 오라고 제안합니까? – ARF

+0

사실, 조금 일찍 결론에 도달했습니다. –

2

모듈의 setup.py__init__ 파일에서 일부 수정을해야 할 것입니다.

보자는 패키지의 이름은 "모듈"이 될 것이라고 당신은 당신이 sub 하위 폴더에 순수 파이썬 코드와 c_sub 하위 폴더에 해당하는 C 코드가 sub하는위한 기능을 가지고있다. 예를 들어 당신의 setup.py :

이제
import logging 
from setuptools.extension import Extension 
from setuptools.command.build_ext import build_ext 
from distutils.errors import CCompilerError, DistutilsExecError, DistutilsPlatformError 

logging.basicConfig() 
log = logging.getLogger(__file__) 

ext_errors = (CCompilerError, DistutilsExecError, DistutilsPlatformError, IOError) 

class BuildFailed(Exception): 
    pass 

def construct_build_ext(build_ext): 
    class WrappedBuildExt(build_ext): 
     # This class allows C extension building to fail. 
     def run(self): 
      try: 
       build_ext.run(self) 
      except DistutilsPlatformError as x: 
       raise BuildFailed(x) 

     def build_extension(self, ext): 
      try: 
       build_ext.build_extension(self, ext) 
      except ext_errors as x: 
       raise BuildFailed(x) 
    return WrappedBuildExt 

setup_args = {'name': 'module', 'license': 'BSD', 'author': 'xxx', 
    'packages': ['module', 'module.sub', 'module.c_sub'], 
    'cmdclass': {} 
    } 

ext_modules = [Extension("module.c_sub._sub", ["module/c_sub/_sub.c"])] 
cmd_classes = setup_args.setdefault('cmdclass', {}) 

try: 
    # try building with c code : 
    setup_args['cmdclass']['build_ext'] = construct_build_ext(build_ext) 
    setup(ext_modules=ext_modules, **setup_args) 
except BuildFailed as ex: 
    log.warn(ex) 
    log.warn("The C extension could not be compiled") 

    ## Retry to install the module without C extensions : 
    # Remove any previously defined build_ext command class. 
    if 'build_ext' in setup_args['cmdclass']: 
     del setup_args['cmdclass']['build_ext'] 
    if 'build_ext' in cmd_classes: 
     del cmd_classes['build_ext'] 

    # If this new 'setup' call don't fail, the module 
    # will be successfully installed, without the C extension : 
    setup(**setup_args) 
    log.info("Plain-Python installation succeeded.") 

당신이 당신의 __init__.py 파일 같은 것을 포함해야합니다 (또는 귀하의 경우 관련 어떤 장소에서) :

try: 
    from .c_sub import * 
except ImportError: 
    from .sub import * 

이 방법은 C에서 버전은 빌드 된 경우 사용되며, 그렇지 않은 경우 일반 파이썬 버전이 사용됩니다. subc_sub이 동일한 API를 제공한다고 가정합니다.

example of setup fileShapely 패키지에서 이와같이 확인할 수 있습니다. 사실 제가 게시 한 대부분의 코드는이 파일에서 복사 (construct_build_ext 함수)되거나이 파일에서 수정되었습니다.

관련 문제