Using cython version 0.11.2, would like to conditionally compile some parts of code on .pyx file.
below is the code in setup.py
CythonExtension('sslip2', sources = ['sslip2.pyx'],
cython_compile_time_env=dict(CONCOM=1),
libraries = ['ssl'],
),
in sslip2.pyx file
IF CONCOM== 1:
def something():
but this is returning below warning and not helpful,
UserWarning: Unknown Extension options: 'cython_compile_time_env'
is it possible to define some variable in Cython Extension and use the same in .pyx file for conditional compilation, I am new to Cython and i think something is missing here, really appreciate any pointers on conditionally compiling the code
Related
toolsTep.py
def HelloWord():
print('hello word')
testpythran.py
from calaTools.toolsTep import *
#pythran export callOtherPyFiles()
def callOtherPyFiles():
HelloWord()
complie pythran testpythran.py
CRITICAL :
I am in trouble. Your input file does not seem to match Pythran's constraints...
testpythran.py:
None:None error: Module 'calaTools.toolsTep' not found.
when two function in save file and it can find ,in diffrent file it occured those errors
When distributing a Python application with Pythran modules, you can either:
declare the module as a regular Python module. After all, they are 100% Python compatible.
declare them as a PythranExtension and Pythran will compile them:
from distutils.core import setup
These two lines are required to be able to use pythran in the setup.py
import setuptools
setuptools.dist.Distribution(dict(setup_requires='pythran'))
from pythran.dist import PythranExtension, PythranBuildExt
setup(...,
ext_modules=[PythranExtension("mymodule", ["mymodule.py"])],
cmdclass={"build_ext": PythranBuildExt})
PythranBuildExt is optional, but necessary to build extensions with different C++ compilers. It derives from distuil’s build_ext by default, but you can change its base class by using PythranBuildExt[base_cls] instead.
all configuration options supported in .pythranrc can also be passed through the optional config argument, in the form of a list, e.g. config=['compiler.blas=openblas']
from pythran doc.https://pythran.readthedocs.io/en/latest/MANUAL.html
The scikit-build distribution provides usage examples of FindF2PY and UseF2PY, but they are incomplete, only providing a partial CMakeLists.txt file without the other required files. Based on the documentation I have not been able to make something that builds.
Following the examples in the scikit-build documentation, I created the following files:
CMakeLists.txt:
cmake_minimum_required(VERSION 3.10.2)
project(skbuild_test)
enable_language(Fortran)
find_package(F2PY REQUIRED)
add_f2py_target(f2py_test f2py_test.f90)
add_library(f2py_test MODULE f2py_test.f90)
install(TARGETS f2py_test LIBRARY DESTINATION f2py_test)
setup.py:
import setuptools
from skbuild import setup
requires=['numpy']
setup(
name="skbuild-test",
version='0.0.1',
description='Performs line integrals through SAMI3 grids',
author='John Haiducek',
requires=requires,
packages=['f2py_test']
)
f2py_test.f90:
module mod_f2py_test
implicit none
contains
subroutine f2py_test(a,b,c)
real(kind=8), intent(in)::a,b
real(kind=8), intent(out)::c
end subroutine f2py_test
end module mod_f2py_test
In addition, I created a directory f2py_test containing an empty init.py.
The output from python setup.py develop shows that scikit-build invokes CMake and compiles my Fortran code. However, it fails to find Python.h while compiling the f2py wrapper code:
[2/7] Building C object CMakeFiles/_f2...kages/numpy/f2py/src/fortranobject.c.o
FAILED: CMakeFiles/_f2py_runtime_library.dir/venv/lib/python3.8/site-packages/numpy/f2py/src/fortranobject.c.o
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc -O3 -DNDEBUG -arch x86_64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk -mmacosx-version-min=10.14 -MD -MT CMakeFiles/_f2py_runtime_library.dir/venv/lib/python3.8/site-packages/numpy/f2py/src/fortranobject.c.o -MF CMakeFiles/_f2py_runtime_library.dir/venv/lib/python3.8/site-packages/numpy/f2py/src/fortranobject.c.o.d -o CMakeFiles/_f2py_runtime_library.dir/venv/lib/python3.8/site-packages/numpy/f2py/src/fortranobject.c.o -c ../../../venv/lib/python3.8/site-packages/numpy/f2py/src/fortranobject.c
In file included from ../../../venv/lib/python3.8/site-packages/numpy/f2py/src/fortranobject.c:2:
../../../venv/lib/python3.8/site-packages/numpy/f2py/src/fortranobject.h:7:10: fatal error: 'Python.h' file not found
#include "Python.h"
^~~~~~~~~~
1 error generated.
First caveat, there may be a better way to do this, as I just figured out how to make scikit-build work by stumbling on your post and looking at documentation. Second caveat, I'm also learning cmake. So, there may be a better way.
There are a couple of things that you'll need to make your example here work. The big one is the second argument of add_f2py_target() isn't the source file. It is either the name of a pre-generated *.pyf, or to let f2py generate one, provide it an argument without the *.pyf extension. The other is adding the include directories for various components.
I made your example work with the following CMakeLists.txt:
cmake_minimum_required(VERSION 3.10.2)
project(skbuild_test)
enable_language(Fortran)
find_package(F2PY REQUIRED)
find_package(PythonLibs REQUIRED)
find_package(Python3 REQUIRED COMPONENTS NumPy)
#the following command either generates or points to an existing .pyf
#if provided an argument with .pyf extension, otherwise f2py generates one (not source code).
add_f2py_target(f2py_test f2py_test)
add_library(f2py_test MODULE f2py_test.f90)
include_directories(${PYTHON_INCLUDE_DIRS})
include_directories(${_Python3_NumPy_INCLUDE_DIR})
target_link_libraries(f2py_test ${PYTHON_LIBRARIES})
install(TARGETS f2py_test LIBRARY DESTINATION f2py_test)
I had a working Cython program which wrapped some C libraries and custom C code. Recently, I had to switch my project to C++, so I renamed all my C code to *.cpp. Cython compiled fine and produced the .so file. However, when I try to import my library in Python, I get the following error.
File "example.py", line 1, in <module>
from tag36h11_detector import detect
ImportError: dlopen(/Users/ajay/Documents/Code/calibration/apriltag_detector/examples/tag36h11_detector.cpython-36m-darwin.so, 2): Symbol not found: _free_detection_payload
Referenced from: /Users/ajay/Documents/Code/calibration/apriltag_detector/examples/tag36h11_detector.cpython-36m-darwin.so
Expected in: flat namespace
in /Users/ajay/Documents/Code/calibration/apriltag_detector/examples/tag36h11_detector.cpython-36m-darwin.so
Because I'm not sure about the source of the error, I'm not sure what relevant information to provide.
Here's my setup.py
from distutils.core import setup, Extension
from Cython.Build import cythonize
import numpy
setup(ext_modules=cythonize(Extension(
name='tag36h11_detector',
sources=["tag36h11_detector.pyx",
"tag36h11_detector/tag36h11_detector.cpp"],
include_dirs=["/usr/local/include/apriltag", numpy.get_include()],
libraries=["apriltag"])))
I compile it with python setup.py build_ext --inplace
Thanks for any assistance!
Add language=c++ to your setup:
setup(ext_modules=cythonize(Extension(
name='XXX',
....
language="c++",
)))
You probably use gcc. The frontend of gcc (and many other compilers) decides whether the file is compiled as C (cc1 is used) or C++ (cc1plus is used) depending on its extension: ".c" is C, ".cpp" is C++.
If you use extra_compile_args=["-v"], in your setup you can see exactly which compiler is used:
Cython creates "tag36h11_detector.c" and because of its extension the C-compiler (cc1) is used.
For the file "tag36h11_detector/tag36h11_detector.cpp" the C++-compiler (cc1plus) is used.`
One of the differences between C and C++ is the name mangling: C expects that the names of the symbols in the object files are not mangled, but C++ mangles it.
For example for a function with signature int test(int) C tells to the linker to search for a symbol called test, but C++ creates a symbol called _Z4testi instead, and thus it cannot be find in the linkage step.
Now, what happens during the linkage? On Linux, the default-behavior of linking a shared object is, that we can have undefined symbols. It is implicitly assumed, that those symbols will be availably during the run-time, when the shared library is loaded. That means the program fails only when the shared object is loaded and the symbol cannot be found, i.e. when you import your module.
You could add extra_link_args=["-Wl,--no-undefined"] to ensure that the compilation fails if there are undefined symbols ain order to not have any surprises during the runtime.
One way to fix it could be too say to C++-compiler to emit unmangled names using extern "C" in your code, as pointed out in the comments.
A less intrusive approach would be to make clear to compiler, that C++-convention is used by adding language="c++" to the setup.
With language="c++", Cython creates "XXX.cpp" (instead of "XXX.c") from "XXX.pyx", and thus gcc chooses C++-compiler for the cythonized file, which is aware of the right name-mangling.
When I compile a cython .pyx file from IdleX the build shell window pops up with a bunch of warnings to close again after less than a second.
I think pyximport uses distutils to build. How can I write the gcc warnings to a file or have the output delay or wait for keypress?
You can add a .pyxbld file to specify Cython build settings.
Say you are trying to compile yourmodule.pyx, simply create a file in the same directory named yourmodule.pyxbld containing:
def make_ext(modname, pyxfilename):
from distutils.extension import Extension
ext = Extension(name = modname,
sources=[pyxfilename])
return ext
def make_setup_args():
return dict(script_args=['--verbose'])
The --verbose flag makes pyximport print gcc's output.
Note that you can easily add extra compiler and linker flags. For example, to use Cython's prange() function you must compile and link against the OpenMP library, this is specified using keywords to the Extension class:
ext = Extension(name = modname,
sources=[pyxfilename],
extra_compile_args=['-fopenmp'],
extra_link_args=['-fopenmp'])
I haven't done anything with cython myself but I guess you could use a commandline for the building. That way you would see all the messages until you close the actual commandline unless some really fatal error happens.
Yes, here is how you could do to get the output in a file (in case the warnings overflow the command prompt) :
This is for Windows, but you can easily adapt for *unices :
SET PYTHONPATH=%PYTHONPATH%;../../../DEPENDENCIES/Cython-0.18
SET PATH=%PATH%;../../../DEPENDENCIES/Cython-0.18/bin
python setup.py build_ext --inplace > output.log
I would like to create a setup.py script for a python package with several submodules that depend on both cython and f2py. I have attempted to use setuptools and numpy.distutils, but have so far failed:
Using setuptools
I am able to compile my cython extensions (and create an installation for the rest of the package) using setuptools. I have, however, been unable to figure out how to use setuptools to generate the f2py extension. After extensive searching, I only found rather old messages like this one that state that f2py modules must be compiled using numpy.distutils.
Using numpy.distutils
I am able to compile my f2py extensions (and create an installation for the rest of the package) using numpy.distutils. I have, however, been unable to figure out how to get numpy.distutils to compile my cython extensions as it always attempts to use pyrex to compile it (and I am using extensions specific to cython) recent. I have done a search to figure out how to get numpy.distutils for cython files and - at least as of a year ago - they recommend applying a monkey patch to numpy.distutils. It seems applying such a monkey patch also restricts the options that can be passed to Cython.
My question is: what is the recommended way to write a setup.py script for packages that depend on both f2py and cython? Is applying a patch to numpy.distutils really the way to go still?
You can just call each separately in your setup.py as in
http://answerpot.com/showthread.php?601643-cython%20and%20f2py
# Cython extension
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
setup(
ext_modules = [Extension( 'cext', ['cext.pyx'] )],
cmdclass = {'build_ext': build_ext},
script_args = ['build_ext', '--inplace'],
)
# Fortran extension
from numpy.distutils.core import setup, Extension
setup(
ext_modules = [Extension( 'fext', ['fext.f90'] )],
)
Your calling context (I think they call this namespace, not sure)
has to change as to what the current object Extension and function
setup() is.
The first setup() call, it's the distutils.extension.Extension
and distutils.core.setup()
The second setup() call, it's the numpy.distutils.core.Extension
and numpy.distutils.core.setup()
Turns out this is no longer true. With both setuptools and distutils (at least the numpy version) it is possible to have extensions with C, Cython and f2py. The only caveat is that to compile f2py modules one must always use numpy.distutils for both the setup and Extension functions. But setuptools can still be used for the installation (for example, allowing the installation of a developer version with python setup.py develop).
To use distutils exclusively you use the following:
from numpy.distutils.core import setup
from numpy.distutils.extension import Extension
To use setuptools, you need to import it before the distutils imports:
import setuptools
And then the rest of the code is identical:
from numpy import get_include
from Cython.Build import cythonize
NAME = 'my_package'
NUMPY_INC = get_include()
extensions = [
Extension(name=NAME + ".my_cython_ext",
include_dirs=[NUMPY_INC, "my_c_dir"]
sources=["my_cython_ext.pyx", "my_c_dir/my_ext_c_file.c"]),
Extension(name=NAME + ".my_f2py_ext",
sources=["my_f2py_ext.f"]),
]
extensions = cythonize(extensions)
setup(..., ext_modules=extensions)
Obviously you need to put all your other stuff in the setup() call. In the above I assume that you'll use numpy with Cython, along with an external C file (my_ext_c_file.c) that will be at my_c_dir/, and that the f2py module is only one Fortran file. Adjust as needed.