Question f2py: Exposition des paramètres des modules "utilisés"


Je suppose que cette question a été abordée quelque part, mais j'ai passé énormément de temps à chercher la réponse, y compris à creuser un peu le code source. J'ai essayé de poser le problème dans le premier paragraphe. Le reste montre un exemple de base du problème.

Je tente de compiler un module qui contient un USE déclaration pointant vers un autre module, plus général. Je préférerais que le module utilisé soit séparé pour pouvoir être utilisé dans plusieurs "packages" comme un ensemble de paramètres généraux. Quand je compile les deux modules en utilisant f2py, tout fonctionne comme annoncé du côté de fortran, mais du côté de python USE semble être ignoré. Si j'autorise f2py à générer un fichier de signature, le fichier contient USE instruction appropriée, mais si je termine la compilation et l'importation depuis la bibliothèque résultante, les paramètres du module utilisé ne sont pas disponibles dans le module qui contient l'instruction use. Voici deux modules illustrant la situation:

MODULE test
    INTEGER, PARAMETER :: a = 1
END MODULE test

MODULE test2
    USE test
    INTEGER, PARAMETER :: b = 2
END MODULE test2

Afin de montrer l'étape intermédiaire, j'ai couru f2py -h test.pyf test.f90 test2.f90. Le fichier de signature suivant est généré. notez que le module "test2" contient "use test":

!    -*- f90 -*-
! Note: the context of this file is case sensitive.

python module test ! in
    interface  ! in :test
        module test ! in :test:test.f90
            integer, parameter,optional :: a=1
        end module test
        module test2 ! in :test:test2.f90
            use test
            integer, parameter,optional :: b=2
        end module test2
    end interface
end python module test

! This file was auto-generated with f2py (version:2).
! See http://cens.ioc.ee/projects/f2py2e/

Si je compile maintenant avec f2py --fcompiler=gfortran -c test.pyf test.f90 test2.f90 J'obtiens test.so (identique à l'exécution f2py --fcompiler=gfortran -m test -c test.f90 test2.f90 sans créer le fichier de signature en premier). L'importation depuis cette bibliothèque en python expose test.test.a et test.test2.b, mais n'expose pas test.test2.a comme on peut le voir ici:

In [1]: import test

In [2]: print test.test.a
1

In [3]: print test.test2.b
2

In [4]: print test.test2.a
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/users/solbrig/svn_checkouts/inversion/satmet/branches/solbrig/rootpath/data/users
/GeoIPS/src/test/<ipython-input-4-bffcf464e408> in <module>() 
----> 1 print test.test2.a

AttributeError: a

Juste pour illustrer cela b est défini correctement dans test2 du point de vue de fortran, le code suivant utilise test2 et imprime les deux b et b:

SUBROUTINE run_test()
    USE test2
    IMPLICIT NONE
    print *, "a = ", a
    print *, "b = ", b
END SUBROUTINE run_test

Après avoir compilé avec "f2py -m run_test -c test.f90 test2.f90 run_test.f90" et obtenu run_test.so, run_test peut être importé en python et fonctionne comme prévu:

In [1]: import run_test

In [2]: run_test.run_test()
 a =            1
 b =            2

Toute aide concernant ce problème serait grandement appréciée.

TL; DR : Quand un module F90 qui contient un USE est compilé par f2py, il n'expose pas les paramètres définis dans le module "used" en tant qu'attributs dans Python.


16
2018-06-17 20:20


origine


Réponses:


J'ai trouvé une solution temporaire à ce problème, mais ce n'est pas optimal. Je continuerai à travailler avec le source f2py pour mieux le comprendre et résoudre le problème dans le code lui-même. Jusque là, c’est ma solution qui a été inspirée par Le commentaire de chatcannon sur le problème que j'ai posté sur le github de Nympy.

Il existe plusieurs manières d'aborder ce problème d'un point de vue temporaire, y compris deux manières de modifier les fichiers .pyf. Je ne veux pas avoir à modifier les fichiers .pyf car ceux-ci deviennent très lourds dans le cadre d'un package plus volumineux. Pour éviter cela, j'ai ajouté des directives f2py à ma source f90.

Prenant l'exemple de ma question initiale:

MODULE test
    INTEGER, PARAMETER :: a = 1
END MODULE test

MODULE test2
    USE test
    INTEGER, PARAMETER :: b = 2
END MODULE test2

ajoutez simplement une directive f2py dans test2 pour montrer à f2py comment définir test2.a:

MODULE test
    INTEGER, PARAMETER :: a = 1
END MODULE test

MODULE test2
    USE test
    !f2py integer, parameter :: a  ! THIS EXPOSES `a` in `test2`
    INTEGER, PARAMETER :: b = 2
END MODULE test2

Importer à partir du résultat test.so expose correctement test2.a:

In [1]: import test

In [2]: print test.test.a
1

In [3]: print test.test.b
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
.../test_solution/<ipython-input-3-798b14f59815> in <module>()
----> 1 print test.test.b

AttributeError: b

In [4]: print test.test2.a
1

In [5]: print test.test2.b
2

6
2017-09-26 07:59