Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1# -*- coding: utf-8 -*- 

2""" 

3@file 

4@brief Cython helpers 

5 

6""" 

7 

8import os 

9import sys 

10import warnings 

11 

12from pyquickhelper.loghelper import run_cmd, noLOG 

13 

14 

15class CustomCythonError(Exception): 

16 """ 

17 raised by function @see fn compile_cython_single_script 

18 when a script cannot be compiled with Cython 

19 """ 

20 pass 

21 

22 

23def compile_cython_single_script(script, skip_warn=True, fLOG=noLOG): 

24 """ 

25 This function considers a script ``.pyx``, writes 

26 the proper setup file, and compiles it. 

27 

28 @param script filename 

29 @param skip_warn skip warnings 

30 @param fLOG logging function 

31 

32 The function applies the steps described in the basic tutorial 

33 :epkg:`The Basics of Cython`. 

34 The function creates a ``setup.py`` 

35 in the same location and compiles it. 

36 

37 The compilation requires a compiler 

38 (not `MinGW <http://www.mingw.org/>`_ or 

39 `Visual Studio (Community Edition) <https://www.microsoft.com/france/visual-studio/produits/community/Default.aspx>`_). 

40 If none was found, Python usually displays an error message like:: 

41 

42 Unable to find vcvarsall.bat 

43 

44 You can also read this old blog post: 

45 `Build a Python 64 bit extension on Windows <http://www.xavierdupre.fr/blog/2013-07-07_nojs.html>`_ 

46 about this file:: ``C:\\Python35_x64\\lib\\distutils\\msvc9compiler.py``. 

47 

48 .. faqref:: 

49 :tag: cython 

50 :title: Compiler une function Cython ? 

51 

52 Cette fonction compile un script 

53 `Cython <http://cython.org/>`_. 

54 Cette extension permet d'implémenter des fonctions Python dans un 

55 pseudo-langage proche du `C <https://en.wikipedia.org/wiki/C_(programming_language)>`_. 

56 Il faut suivre les instructions décrite dans le tutorial 

57 :epkg:`The Basics of Cython` 

58 pour réussir à utiliser une fonction codée en Cython. 

59 C'est ce que fait la fonction :func:`compile_cython_single_script`. 

60 

61 Etant donné que la partie en pseudo C est compilée afin de la rendre beaucoup 

62 plus rapide, la partie la plus difficile est généralement celle qui consiste à faire 

63 en sorte que l'interpréteur Python trouve le <b>bon</b> compilateur. 

64 Ce compilateur est nécessairement le même que celui utilisé pour compiler 

65 Python et celui-ci change à chaque version. 

66 Voir 

67 `Compiling Python on Windows <https://docs.python.org/3/using/windows.html?highlight=visual%20studio#compiling-python-on-windows>`_ 

68 et faire attention à la version de Python que vous utilisez. 

69 """ 

70 ext = os.path.splitext(script)[-1] 

71 if ext != ".pyx": 

72 raise ValueError("no extension .pyx: " + script) 

73 if not os.path.exists(script): 

74 raise FileNotFoundError(script) 

75 

76 name = os.path.split(script)[-1] 

77 namen = os.path.splitext(name)[0] 

78 setup_script = """ 

79 from distutils.core import setup 

80 from Cython.Build import cythonize 

81 setup( 

82 name='{1}', 

83 ext_modules=cythonize("{0}", 

84 compiler_directives={{'language_level': {2}}}) 

85 ) 

86 """.replace(" ", "").format(name, namen, sys.version_info[0]) 

87 

88 current, name = os.path.split(script) 

89 filename = os.path.join(os.path.dirname(script), name + ".setup.py") 

90 with open(filename, "w") as f: 

91 f.write(setup_script) 

92 

93 cmd = sys.executable + " -u {0} build_ext --inplace".format(filename) 

94 

95 out, err = run_cmd(cmd, wait=True, fLOG=fLOG, change_path=current) 

96 if len(err) > 0: 

97 if skip_warn: 

98 do_raise = False 

99 lines = err.split("\n") 

100 for line in lines: 

101 if len(line) > 0 and not line.startswith(" "): 

102 if "UserWarning" not in line: 

103 do_raise = True 

104 break 

105 else: 

106 do_raise = True 

107 if do_raise: 

108 with open(script, "r", encoding="utf-8") as f: 

109 content = f.read() 

110 raise CustomCythonError( 

111 "CMD:\n{0}\nOUT:\n{1}ERR:\n{2}\nSCRIPT:\n{3}".format(cmd, out, err, content)) 

112 else: 

113 warnings.warn( 

114 "[compile_cython_single_script] CMD:\n{0}\nOUT:\n{1}ERR:\n{2}".format(cmd, out, err)) 

115 return out