f2py:从“已使用”模块中公开参数

时间:2013-06-17 20:20:29

标签: python numpy fortran90 f2py

我认为这个问题已在某处得到解决,但我花了大量时间寻找答案,包括深入研究源代码。我试图把问题放在第一段。其余部分显示了问题的基本示例。

我正在尝试编译一个包含USE语句的模块,该语句指向另一个更通用的模块。我更希望将使用过的模块保持独立,以便可以将它作为一组常规设置用于多个“包”中。当我使用f2py编译这两个模块时,一切都像fortran那样宣传,但是从python端USE似乎被忽略了。如果我允许f2py生成签名文件,则该文件包含USE语句,但如果我完成编译并从结果库导入,则使用的模块中的参数在包含的模块中不可用使用声明。以下是说明情况的两个模块:

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

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

为了显示中间步骤,我运行了f2py -h test.pyf test.f90 test2.f90。生成以下签名文件;请注意,“test2”模块包含“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/

如果我现在使用f2py --fcompiler=gfortran -c test.pyf test.f90 test2.f90进行编译,我将获得test.so(与运行f2py --fcompiler=gfortran -m test -c test.f90 test2.f90相同,而不首先创建签名文件)。在python中从这个库导入暴露了test.test.a和test.test2.b,但是没有公开test.test2.a,如下所示:

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

为了说明从fortran的角度在test2中正确定义b,以下代码使用test2并打印bb

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

使用“f2py -m run_test -c test.f90 test2.f90 run_test.f90”进行编译并获取run_test.so之后,可以在python中导入run_test并按预期工作:

In [1]: import run_test

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

对此问题的任何帮助将不胜感激。

TL; DR :当包含USE的F90模块由f2py编译时,它不会将“used”模块中定义的参数公开为Python中的属性。

1 个答案:

答案 0 :(得分:6)

我找到了解决此问题的临时解决方案,但这并不是最佳解决方案。我将继续使用f2py源代码,以便我能够更好地理解它并在代码本身内解决问题。在此之前,这是我的解决方案,其灵感来自chatcannon's comment to the issue I posted to nympy's github

有几种方法可以从临时角度处理此问题,包括修改.pyf文件的几种方法。我不想修改.pyf文件,因为它变得非常麻烦,作为更大的包的一部分。为了避免这种情况,我在我的f90源代码中添加了f2py指令。

以我原来的问题为例:

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

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

只需在test2中添加一个f2py指令即可显示f2py如何定义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

从结果test.so导入正确公开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