16

我假设这个问题已经在某个地方得到解决,但是我花了很多时间四处寻找答案,包括深入研究源代码。我试图把问题放在第一段。其余部分显示了该问题的基本示例。

我正在尝试编译一个包含USE指向另一个更通用模块的语句的模块。我更愿意将使用的模块分开,以便它可以在多个“包”中用作一组通用设置。当我使用 f2py 编译这两个模块时,一切都像从 fortran 端宣传的那样工作,但从 python 端USE似乎被忽略了。如果我允许 f2py 生成签名文件,则该文件包含USE适当的语句,但如果我完成编译并从生成的库中导入,则使用的模块中的参数在包含 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”模块包含“使用测试”:

!    -*- 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/

如果我现在用我编译得到 test.so (与不先创建签名文件的情况下f2py --fcompiler=gfortran -c test.pyf test.f90 test2.f90运行相同)。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

只是为了说明b从 fortran 的角度在 test2 中正确定义的内容,以下代码使用 test2 并同时打印band b

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:当包含 a 的 F90 模块USE由 f2py 编译时,它不会将“已使用”模块中定义的参数作为 Python 中的属性公开。

4

1 回答 1

6

我找到了这个问题的临时解决方案,但它不是最佳的。我将继续研究 f2py 源代码,以便更好地理解它并解决代码本身的问题。在那之前,这是我的解决方案,灵感来自chatcannon 对我发布到 nympy 的 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
于 2013-09-26T07:59:54.080 回答