F2PY:从“已使用”模块中暴露参数

16

我认为这个问题已经得到了解决,但是我花费了大量时间来寻找答案,包括深入挖掘源代码。第一段展示了我的问题。其余部分展示了问题的基本示例。

我尝试编译一个包含指向另一个更通用的模块的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的角度来看b已经被正确定义,以下代码使用test2并打印出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中导入并正常工作:

In [1]: import run_test

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

非常感谢能够提供帮助解决此问题。

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


1
我会尝试解答,但他们在过去几年里似乎没有做太多事情。我已将这个问题发送到scipy邮件列表中。 - Vorticity
我认为这个问题有一个临时解决方案,我会在星期一测试后发布。我目前也正在研究f2py源代码,以寻求更优化的解决方案。 - Vorticity
@Marcin 我把临时解决方案作为答案添加了进去。它相当简单,但并不是我所希望的。希望我能有机会很快花些时间研究f2py源代码。 - Vorticity
@Juanlu001 我把临时解决方案作为答案添加了进去。它相当简单,但并不是我所希望的。希望我能有机会很快花一些时间研究f2py源代码。 - Vorticity
@Vorticity,f2py源代码是我见过的最复杂的噩梦,祝你好运。 - astrojuanlu
显示剩余5条评论
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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接