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
6"""
8import os
9import sys
10import warnings
12from pyquickhelper.loghelper import run_cmd, noLOG
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
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.
28 @param script filename
29 @param skip_warn skip warnings
30 @param fLOG logging function
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.
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::
42 Unable to find vcvarsall.bat
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``.
48 .. faqref::
49 :tag: cython
50 :title: Compiler une function Cython ?
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`.
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)
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])
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)
93 cmd = sys.executable + " -u {0} build_ext --inplace".format(filename)
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