Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

f2py in numpy 2.0.1 does not expose variables the way numpy 1.26 did. How can I access Fortran variables in Python?

Tags:

python

numpy

f2py

I used to run a collection of Fortran 95 subroutines from Python by compiling it via f2py. In the Fortran source I have a module with my global variables:

   MODULE GEOPLOT_GLOBALS
     IMPLICIT NONE
     INTEGER, PARAMETER :: N_MAX = 16
     INTEGER, PARAMETER :: I_MAX = 18
     INTEGER, PARAMETER :: J_MAX = 72
     ...
   END MODULE GEOPLOT_GLOBALS

The compiled file has the name "geoplot.cpython-312-darwin.so" and is in a subfolder named "geo". When using f2py in numpy 1.26, I could do this:

import geo.geoplot as geo
maxN = geo.geoplot_globals.n_max
maxI = geo.geoplot_globals.i_max
maxJ = geo.geoplot_globals.j_max

Now, with numpy 2.0.1, I do the same but get the error message

AttributeError: module 'geo.geoplot' has no attribute 'geoplot_globals'

Which can be confirmed by listing the __dict__ attribute or using the getmembers module: They all list the Fortran subroutines and modules which contain source code, except for the geoplot_globals module which contains only variable declarations.

So my question is: How am I supposed to access global Fortran variables from Python when using numpy 2.0? And please do not suggest to write all to a file in Fortran only to read it in Python. There should be a more direct way.

like image 877
Peter Kämpf Avatar asked Sep 03 '25 03:09

Peter Kämpf


1 Answers

This must be a bug in f2py. See here: https://github.com/numpy/numpy/issues/27167

What got me unstuck is an ugly workaround: I simply added some useless dummy code to the module, like that:

MODULE GEOPLOT_GLOBALS
    USE MOD_TYPES
    IMPLICIT NONE
    INTEGER, PARAMETER :: N_MAX = 16
    INTEGER, PARAMETER :: I_MAX = 18
    INTEGER, PARAMETER :: J_MAX = 72
    ...
    CONTAINS
    SUBROUTINE DUMMY (UNSINN)
        INTEGER :: UNSINN
        OPEN(UNIT=29, FILE="FOR29.txt", STATUS = 'UNKNOWN')
        WRITE(29,"(I8)") UNSINN
        CLOSE (29)
    END SUBROUTINE DUMMY
END MODULE GEOPLOT_GLOBALS

Now the before missing module is carried over into Python and can be accessed in the usual way.

>>> print(geo.geoplot_globals.__doc__)
n_max : 'i'-scalar
i_max : 'i'-scalar
j_max : 'i'-scalar
...
like image 81
Peter Kämpf Avatar answered Sep 04 '25 22:09

Peter Kämpf