F2py with Openmp gives import error in Python - python

I am able to compile the minimal working example below in Fortran which uses Openmp and run to give the expected result (prints 1).
subroutine test
use omp_lib
write(*,*) omp_get_num_threads()
end subroutine
However using this in python with f2py gives the error:
ImportError: DLL load failed: A dynamic link library (DLL) initialization routine failed.
I have used the dependency walker to test if the issue is in linking to the openmp dll, however the following .dll is linked in both the fortran executable and the .pyd compiled from f2py:
c:\tdm-gcc-64\bin\LIBGOMP_64-1.DLL
Therefore I am confused as to why python would fail to load the .dll, as it appears to be linked correctly from f2py. The f2py command that I'm using to generate the .pyd is
python -m numpy.f2py -c -m %output% %input%.f90 --fcompiler=gnu95 --compiler=mingw32 --f90flags="-fopenmp " -lgomp
Any help would be greatly appreciated, thanks.
EDIT: I have tested this with another windows PC with the same installation setup, and get the same error message. Am I missing something?
EDIT 2: Apparently this program wouldn't actually work in f2py, so is bad example. My apologies. I'm actually working with subroutines, which are able to work with f2py correctly so long as no openmp commands are present.
EDIT 3: I have replaced the example code to be a subroutine instead of program due to feedback from Pierre de Buyl, though this makes no difference to my question.

This works for me:
tesf.f95
subroutine nthreads
!$ use omp_lib
integer :: nt
nt = 0
!$ nt = omp_get_max_threads()
write(*,*) 'Nthreads'
write(*,*) nt
end subroutine
Compile with:
f2py -c test.f95 -m test --f90flags='-fopenmp' -lgomp -lpthread --compiler=mingw32 --fcompiler=gfortran
If I run:
python -c "import test; test.nthreads()"
The result is:
Nthreads
8

It appears that the problem was in using tdm-gcc-64 as a compiler, and so I am instead using a mingw64 installation which works as expected.

Related

How to execute `f2py`?

How can I wrap in the f2py module?
I mean, I am reading a few tutorials that say I should execute
f2py FIB1.f -m FIB2 -h FIB1.pyf
However, I don't know where I have to execute that, for sure not in spyder or I am doing something wrong.
Why?
Because I execute this code that should create the extension module of Fortran with Python from my subroutine in Fortran, however an error is generated.
my Fortran subroutine:
SUBROUTINE FIB(A,N)
INTEGER N
REAL*8 A(N)
DO I=1,N
IF (I.EQ.1) THEN
A(I) = 0.0D0
ELSEIF (I.EQ.2) THEN
A(I) = 1.0D0
ELSE
A(I) = A(I-1) + A(I-2)
ENDIF
ENDDO
END
What I'm executing in Python:
import numpy.f2py as f2py
f2py FIB1.f -m FIB2 -h FIB1.pyf
The error is this one:
runfile('F:/SLB/Larryf2py/teste.py', wdir='F:/SLB/Larryf2py')
File "F:/SLB/Larryf2py/teste.py", line 9
f2py FIB1.f -m FIB2 -h FIB1.pyf
^
SyntaxError: invalid syntax
As far as I know, not sure, It should generate something like:
# File setup.py
def configuration(parent_package='',top_path=None):
from numpy.distutils.misc_util import Configuration
config = Configuration('',parent_package,top_path)
config.add_extension('m',
sources = ['m.pyf','foo.c'])
return config
if __name__ == "__main__":
from numpy.distutils.core import setup
setup(**configuration(top_path='').todict())
This example of what is generated is to C but I think its something like that to Fortran too.
What I think? That I should run the first code in another place of the Python...
I tried to reproduce this.
Are you adding f2py command inside your Python code? If yes, that's not good.
The line f2py FIB1.f -m FIB2 -h FIB1.pyf needs to be in command line, not inside any *.py script.
From F2PY Users Guide and Reference Manual
f2py is a program/compiler from The purpose of the F2PY –Fortran to Python interface generator– project is to provide a connection between Python and Fortran languages. F2PY is a Python package (with a command line tool f2py and a module f2py2e) that facilitates creating/building Python C/API extension modules that make it possible.
In additon, here is detailed explanation on how to use f2py .
There might be some other problems in OP's question but for the moment most vital is this one. Like the Fortran subrotuine is not using implicit none, etc.
Well I found an answer.
Looks like in this version of anaconda one is supossed tu put like
Python c:\user\anaconda3\scripts\f2py.py FIB1.f -m FIB2 -h FIB1.py
so this way that f2py.py part was substituted for all of that. For sure I'll have more trouble in the future with this module but so far my doubts are clear.
If you want to convert fortran into a python object using a python code, the following will work:
from numpy import f2py
with open('path_to_fotran_code') as sourcefile:
sourcecode = sourcefile.read()
f2py.compile(sourcecode, modulename='test_module', verbose=1,
extra_args= '--verbose'
'--compiler=mingw32')
import test_module
In case you do not have mingw32 you can use --compile=msvc (I ran into problems trying to use msvc which I could never solve with all the internet help).
Also ensure that your windows path environment is configured to point the fortran compiler path.
f2py is not a Python command, you cannot execute it in the Python shell or inside a .py source file. It is an executable command. You must execute it in your system's shell.
You still did not answer which operating system you have, but if it is Windows, you must run it in the CMD.exe command prompt or in PowerShell. If it is Linux or similar, run it in bash or similar shell. You must run it in the same directory (folder), where the Fortran source file is located.

f2py is not able to link with NetCDF library -

I am trying install some Python modules in my system using f2py, which are related to an ocean model (in Fortran 90). I am facing some problems with f2py. To be specific, the f2py is unable to link with the NetCDF library even though I have the required library and include files installed. I am using Python 2.7 with Anaconda 2 on Ubuntu16.04 on a 64-bit machine. I'm using gfortran.
To test it's working, I wrote a small code - an f90 module that contains a small subroutine. The subroutine performs a basic math task, and calls a NetCDF routine that prints the NetCDF version installed. The module (testsub.f90) is as follows:
module testsub
implicit none
contains
subroutine f_sum(a, b, s)
!#include 'netcdf.inc'
use netcdf
real(8) :: a, b, s
s = a+b;
!Calls a function that prints the netcdf version
write(*,*) trim(nf90_inq_libvers())
end subroutine f_sum
end module
The makefile for testsub is:
#Fortran compiler
FC=gfortran
NCLIB = -L/home/sonaljit/anaconda2/lib -lnetcdf -lnetcdff -L/usr/lib/python2.7/config-x86_64-linux-gnu -lpython2.7
NCINC = -I/home/sonaljit/anaconda2/include
#f2py and flags
F2PY = /home/sonaljit/anaconda2/bin/f2py
PYFLAGS = "-fPIC -g -O2 -fdefault-real-8"
pytest : testsub.f90
$(F2PY) --fcompiler=$(FC) --f90flags=$(PYFLAGS) -c $(NCINC) -m testpymod testsub.f90 $(NCLIB)
clean :
rm testpymod.so
I have the NetCDF library and include files installed in the given paths. When I run the makefile using make pytest, I get the following error:
/usr/bin/ld: /home/sonaljit/anaconda2/lib/libnetcdf.a(netcdf.o): relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
/home/sonaljit/anaconda2/lib/libnetcdf.a: error adding symbols: Bad value
collect2: error: ld returned 1 exit status
However, I am not seeing this error when I am commenting out the NetCDF lines in the module. It seems f2py is not able to link to NetCDF routines. What can be the error here? Is it due to the structure of the code? Or, do I need to include some other library?
You are compiling a shared (dynamic) library and you should use a shared library version of NetCDF.
If you installed NetCDF yourself (as suggested by the path in your /home/sonaljit), you should install the .so version and link with this version.

f2py how do i fix Symbol not found errors such as ___kmpc_begin

I currently have the error 2): Symbol not found ___kmpc_begin. I have encountered other symbol not found errors but this message doesnt provide me any information on how to correct the problem.
If it helps, I am compiling the code with ifort using the following command:
f2py -c --fcompiler=intelem --f77exec=/usr/bin/ifort -m main main.f
Where can I look to be able to figure out what the Symbol not found error means and how to correct it?
Basically what this error is saying is that the library is not included in the .so file being created by f2py. There may be some extra library files here and command options that you don't need but at least this gives a clue on how to fix the symbol not found error.
To fix the "2): Symbol not found ___kmpc_begin" I did the following but you can apply this idea to other Symbol not found errors.
First run this:
f2py -m main -h sgnFile.pyf main.f
Then run this:
f2py -c --fcompiler=intelem --f77exec=/usr/bin/ifort -L/opt/intel/composer_xe_2015.0.077/mkl/lib -L/opt/intel/composer_xe_2015.0.077/compiler/lib -llibiomp5 -lmkl_intel_lp64 -lmkl_sequential -lmkl_core -lmkl_intel_thread -lpthread -lm -m main sgnFile.pyf main.f *.o
I put the files from the intel folder in the same folder containing my main.f file and that allowed me to be able to use pycharm to compile my application so you may need to do this also.
Hope this helps!

How can I build my C extensions with MinGW-w64 in Python?

So I have a few Python C extensions I have previously built for and used in 32 bit Python running in Win7. I have now however switched to 64 bit Python, and I am having issues building the C extension with MinGW-w64.
I made the changes to distutils as per this post, but I am getting some weird errors suggesting something is wrong:
$ python setup.py build
running build
running build_ext
building 'MyLib' extension
c:\MinGW64\bin\x86_64-w64-mingw32-gcc.exe -mdll -O -Wall -Ic:\Python27\lib\site-packages\numpy\core\include -Ic:\Python27\include -Ic:\Python27\PC -c MyLib.c -o build\temp.win-amd64-2.7\Release\mylib.o
MyLib.c: In function 'initMyLib':
MyLib.c:631:5: warning: implicit declaration of function 'Py_InitModule4_64' [-Wimplicit-function-declaration]
writing build\temp.win-amd64-2.7\Release\MyLib.def
c:\MinGW64\bin\x86_64-w64-mingw32-gcc.exe -shared -s build\temp.win-amd64-2.7\Release\mylib.o build\temp.win-amd64-2.7\Release\MyLib.def -Lc:\Python27\libs -Lc:\Python27\PCbuild\amd64 -lpython27 -o build\lib.win-amd64-2.7\MyLib.pyd
build\temp.win-amd64-2.7\Release\mylib.o:MyLib.c:(.text+0x13d): undefined reference to `__imp_PyExc_ValueError'
build\temp.win-amd64-2.7\Release\mylib.o:MyLib.c:(.text+0x1275): undefined reference to `__imp_PyExc_ValueError'
build\temp.win-amd64-2.7\Release\mylib.o:MyLib.c:(.text+0x1eef): undefined reference to `__imp_PyExc_ImportError'
build\temp.win-amd64-2.7\Release\mylib.o:MyLib.c:(.text+0x1f38): undefined reference to `__imp_PyExc_AttributeError'
build\temp.win-amd64-2.7\Release\mylib.o:MyLib.c:(.text+0x1f4d): undefined reference to `__imp_PyCObject_Type'
build\temp.win-amd64-2.7\Release\mylib.o:MyLib.c:(.text+0x1f61): undefined reference to `__imp_PyExc_RuntimeError'
build\temp.win-amd64-2.7\Release\mylib.o:MyLib.c:(.text+0x1fc7): undefined reference to `__imp_PyExc_RuntimeError'
build\temp.win-amd64-2.7\Release\mylib.o:MyLib.c:(.text+0x1ffe): undefined reference to `__imp_PyExc_RuntimeError'
build\temp.win-amd64-2.7\Release\mylib.o:MyLib.c:(.text+0x2042): undefined reference to `__imp_PyExc_RuntimeError'
build\temp.win-amd64-2.7\Release\mylib.o:MyLib.c:(.text+0x206c): undefined reference to `__imp_PyExc_RuntimeError'
build\temp.win-amd64-2.7\Release\mylib.o:MyLib.c:(.text+0x208a): more undefined references to `__imp_PyExc_RuntimeError' follow
build\temp.win-amd64-2.7\Release\mylib.o:MyLib.c:(.text+0x20a7): undefined reference to `__imp_PyExc_ImportError'
collect2.exe: error: ld returned 1 exit status
error: command 'x86_64-w64-mingw32-gcc' failed with exit status 1
I have googled around quite a bit to find information, but it's not easy to find a definite answer. Could someone shed some light on this? What further changes should I do to be able to successfully build C extensions for 64 bit Python in Win7?
EDIT:
After some helpful pointers in cgohlke's comments below I managed to generate libpython27.a. However after following the advice on this post (2nd to last) I still had a the __imp_Py_InitModule4_64 error. After some serious Google-fu I managed to trip over this post telling me to rename the Py_InitModule4 line to Py_InitModule4_64. After that everything worked swimmingly.
This worked for me with Python 3.3 :
create static python lib from dll
python dll is usually in C:/Windows/System32; in msys shell:
gendef.exe python33.dll
dlltool.exe --dllname python33.dll --def python33.def --output-lib libpython33.a
mv libpython33.a C:/Python33/libs
use swig to generate wrappers
e.g., swig -c++ -python myExtension.i
wrapper MUST be compiled with MS_WIN64, or your computer will crash when you import the class in Python
g++ -c myExtension.cpp -I/other/includes
g++ -DMS_WIN64 -c myExtension_wrap.cxx -IC:/Python33/include
shared library
g++ -shared -o _myExtension.pyd myExtension.o myExtension_wrap.o -lPython33 -lOtherSharedLibs -LC:/Python33/libs -LC:/path/to/other/shared/libs
make sure all shared libs (gdal, OtherSharedLibs) are in your PATH
(windows does not use LD_LIBRARY_PATH or PYTHONPATH)
in Python, just: import myExtension
voila!
I realize this is an old question, but it is still the top search result. Today, in 2019, I was able to do this:
https://github.com/PetterS/quickjs/commit/67bc2428b8c0716538b4583f4f2b0a2a5a49106c
In short:
Make sure a 64-bit version of mingw-w64 is in the PATH.
Monkey-patch distutils:
import distutils.cygwinccompiler
distutils.cygwinccompiler.get_msvcr = lambda: []
Some differences in the shell w.r.t. escaping.
extra_link_args = ["-Wl,-Bstatic", "-lpthread"] in order to link statically and not have extra runtime deps.
pipenv run python setup.py build -c mingw32 now works.
Here is a example code for VC++ Build Tools
https://github.com/starnight/python-c-extension/tree/master/00-HelloWorld
You could try:
python setup.py -c mingw32
However this is not work for me.
My Solution is:
install Anaconda 64bit python 3.6
install mingw64
add mingw64/bin to PATH
compile dll from c file by
gcc -c libmypy.c -IC:\Users\{user_name}\Anaconda3\pkgs\python-3.6.4-h6538335_1\include
gcc -shared -o libmypy.dll libmypy.o -LC:\Users\{user_name}\Anaconda3\pkgs\python-3.6.4-h6538335_1\libs -lPython36
load dll file in .py script
from ctypes import *
m = cdll.LoadLibrary(r"C:\{path_to_dll}\libmypy.dll")
print(m.hello())
I created a monkey-patch for setuptools to let you to build_ext with mingw64 on Windows easily. See https://github.com/imba-tjd/mingw64ccompiler
I used this thread to wade through learning how to make a C extension, and since most of what I learned is in it, I thought I'd put the final discovery here too, so that someone else can find it if they are looking.
I wasn't trying to compile something big, just the example in Hetland's Beginning Python. Here is what I did (the example C pgm is called palindrome.c). I'm using Anaconda with python 3.7 in it, and the TDM-GCC version of MinGW64. I put all of the tools used into my Path, and all of the paths needed in PYTHONPATH, and the ..\Anaconda3 directory into PYTHON_HOME. I still ended up using explicit paths on some things.
I created the libpython37.a library with gendef.exe and dlltool.exe as Mark said above, and put it in ..\Anaconda3\libs.
I followed the prescription in Hetland:
gcc -c palindrome.c
gcc -I$PYTHON_HOME -I$PYTHON_HOME/Include -c palindrome_wrap.c
The second failed, the compiler couldn't find Python.h, the following worked:
gcc -I[somedirectories]\Anaconda3\Include -c palindrome_wrap.c
I then did, as many have said, including Hetland 3rd ed.,
gcc -shared palindrome.o palindrome_wrap.o [somedirectories]/Anaconda3/libs/libpython37.a -o _palindrome.dll
This did not work. Even with the Load Library cswu used (which I found elsewhere, too).
So I gendef'd _palindrome.dll and couldn't find the function in it, "is_palindrome" in the exports. I went through some of the SWIG documentation, and declared the function both in the %{ %} section and below it, both extern, that finally got the function extern'd in palindrome_wrap.c as it should have been. But no export, so I went back into palindrome.c and redeclared the function as:
declspec(dllexport) extern int __stdcall is_palindrome(char* text)
and redeclared it in palindrome.i in both places as above with this signature.
Partial success! It got listed in the Export section when I gendef'd _palindrome.dll and I could do cswu's call using Load Library. But still not do what Hetland says and do
import _palindrome
in Python.
Going back to all the sources again, I could not figure this out. I finally started reading the SWIG documentation from the beginning leaving no stone unturned -- Searching through the manual doesn't produce the place found.
At the end of Introduction Sec. 2.7 Incorporating Into a Build System, under the sample Make process, it says:
"The above example will generate native build files such as makefiles, nmake files and Visual Studio projects which will invoke SWIG and compile the generated C++ files into _example.so (UNIX) or _example.pyd (Windows). For other target languages on Windows a dll, instead of a .pyd file, is usually generated."
And that's the answer to the last problem:
The compile step for the dll should read:
gcc -shared palindrome.o palindrome_wrap.o [somedirectories]/Anaconda3/libs/libpython37.a -o _palindrome.pyd
(I didn't go back and change out my declspec declarations so I don't know whether they were necessary, so they were still there too).
I got a file, _palindrome.pyd
Which if in the PYTHONPATH (mine was local) works, and one can then do
import _palindrome
from _palindrome import is_palindrome
and use the exported, properly wrapped and packaged C function, compiled with TDM-GCC, in python as promised. gcc, which is MinGW64 in a different installation, knows how to do the .pyd file. I diffed the dll and pyd since they were the same byte length. They are not the same at hundreds of points.
Hope this helps someone else.

How to get program to not throw "Error: Can't load Floyd's algorithm library"

another question for all of you-
So i am trying to get a program called Pysomap to work (its basically ISOMAP but for python[http://web.vscht.cz/spiwokv/pysomap/]), i follow the directions best as i can, building it on Ubuntu, Windows, and Fedora (prebuilt libraries), but cant seem to get it to work. On windows (which is the preferred implementation platform), every time i go to python and import pysomap, it gives me the above error. Anybody know how to solve this?
Thanks
-J
In the pysomap directory, create a setup.py file with the following content:
from distutils.core import setup, Extension
setup(name="pysomap",
version="2007.07",
url ="http://web.vscht.cz/spiwokv/pysomap/",
description="A library for isometric feature mapping.",
license='Unknown',
author="Vojtech Spiwok",
py_modules=["floyd", "pysomap"],
ext_modules=[Extension('_floyd', ["floyd_wrap.c", "floyd.c"])]
)
Build the _floyd extension (assuming you have a Python distutils compatible C compiler installed):
python setup.py build_ext --inplace
Run demo.py:
python demo.py
Calculating distance matrix ............ 2.24 s
Using epsilon-isomap, epsilon = 0.500000, calculating 2-dimensional embedding
Calculating graph matrix ............... 1.21 s
Calculating the shortest path matrix ... 2.22 s
Multidimensionally scalling ............ 7.11 s
--------------------------------------------------
Total procedure ........................ 12.79 s
I had a look at the code because Isomap is a cool algorithm. The code doesn't look like it was written by someone familiar with Python, and the whole floyd extension module compilation is sort of shoddy - it actually didn't build for me, and I'm pretty sure that's your problem (they catch the import exception for the module and print out the error that you give).
I changed some hard-coded stuff in build_floyd.sh to different hard-coded values for my system. (A proper build system would make this unnecessary). Here's what worked in my Ubuntu system. I tested and it ran ok.
#!/bin/sh
# run this script to generate library for Floyd's
# algorithm library
echo "generating input files using SWIG ..."
swig -python floyd.i
echo "compiling ..."
# change compiler if you use other than gcc
gcc -c floyd.c floyd_wrap.c -I/usr/include/python2.6 -fPIC
echo "linking ..."
ld -shared floyd.o floyd_wrap.o -o _floyd.so
#echo "for SELinux you must run chcon ..."
#chcon -t textrel_shlib_t _floyd.so
You may also have to change the first line in demo.py to #!/usr/bin/env python.
This source code is over 5 years old and the build script for floyd looks to assume hard-coded python2.4.
It seems pretty clear that your floyd module did not build. You will most likely have to go back to the build step and ensure that you are properly generating a _floyd.so.
If you built it correctly, then this should not fail for you:
python -c "import _floyd"

Categories

Resources