8

我正在使用 Fortran 创建一个 Python 模块f2py。如果在 Fortran 模块中遇到错误,我想在 Python 程序中产生错误(包括错误消息)。考虑以下示例:

Fortran 代码(test.f):

subroutine foo(a,m)

  integer :: m,i
  integer, dimension(m) :: a
  !f2py intent(in) :: m
  !f2py intent(in,out) :: a
  !f2py intent(hide), depend(a) :: m=shape(a)

  do i = 1,m
    if ( a(i) .eq. 0 ) then
      print*, 'ERROR HERE..?'
    end if 
    a(i) = a(i)+1
  end do

end subroutine

这个非常简单的程序添加1a. a(i)但如果等于 0,应该会产生错误。随附的 Python 代码:

import test

print test.foo(np.array([1,2],dtype='uint32'))
print test.foo(np.array([0,2],dtype='uint32'))

现在的输出是:

[2 3]
ERROR HERE..?
[1 3]

我希望 Python 程序保留错误。请帮忙。

回答

stopFortran 中的命令正是这样做的。考虑更新的 Fortran 代码:

subroutine foo(a,m)

  integer :: m,i
  integer, dimension(m) :: a
  !f2py intent(in) :: m
  !f2py intent(in,out) :: a
  !f2py intent(hide), depend(a) :: m=shape(a)

  do i = 1,m
    if ( a(i) .eq. 0 ) then
      print*, 'Error from Fortran'
      stop
    end if 
    a(i) = a(i)+1
  end do

end subroutine

现在的输出是:

[2 3]
Error from Fortran

即 Python 代码在出错后不会继续。

4

2 回答 2

4

我建议numpy社区添加一个额外的 f2py“增强”(raise_python_exception),这使得在 Fortran 中定义一个字符串变量成为可能,如果非空将导致 Python 在函数返回时引发异常。

因此,在 Fortran 中,您将编写如下内容:

subroutine calc_dq(q, temp, dq, error_mesg)
  !f2py raise_python_exception error_mesg

  real, intent(in) :: q, temp
  real, intent(out) :: dq

  character(len=100), intent(out) :: error_mesg

  if (.not. init_called()) then
     error_mesg = "`init` hasn't been called."
  else
     call q_flux_function(q, temp, dq)
  endif
end subroutine calc_dq

并从 Python 调用error_mesg变量的内容作为异常的内容:

In [2]: calc_dq(1.0, 300.)
---------------------------------------------------------------------------
Exception                                 Traceback (most recent call last)
<ipython-input-8-c0ce0cb9cda1> in <module>()
----> 1 calc_dq(1.0, 300.)

Exception: `init` hasn't been called.

我认为这是从 Fortran 引发异常的一种非常方便的方法,因为它允许轻松定义异常消息。我已将我的建议放在 github 上

于 2015-10-21T10:19:05.700 回答
1

f2py确实提供了一些可用于引发异常的语句。在此处查看详细信息:

http://cens.ioc.ee/projects/f2py2e/usersguide/#statements

特别是看callstatementwhich描述了如何添加f2py_success = 0哪个会触发异常。

我不确定这是否会帮助您调试 fortran 库的内部,但至少这是一个开始。

于 2014-01-23T21:32:48.957 回答