2013-08-02 10 views
7

Tworzę moduł Pythona w Fortranie przy użyciu f2py. Chciałbym utworzyć błąd (w tym komunikat o błędzie) w programie Python, jeśli napotkany błąd w module Fortran. Rozważmy następujący przykład:Zatrzymanie kodu Pythona w module (Fortran) błąd modułu przy użyciu f2py?

kod 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 

to bardzo prosty program dodaje 1 do każdego elementu a. Ale powinien spowodować błąd, jeśli a(i) jest równa zero. Towarzyszący kod Python:

import test 

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

Wyjście jest teraz:

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

Ale Chcę program Python trzymać błędu. Proszę pomóż.

Odpowiedź

Komenda w Fortran stop robi dokładnie to. Rozważmy zaktualizowany kod 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 

Wyjście jest teraz:

[2 3] 
Error from Fortran 

Tj kod Pythona nie jest kontynuowany po błędzie.

+1

Czy próbujesz podnieść wyjątek Python z modułu Fortran? – user2357112

+1

Tak, to jest dokładnie to, co próbuję zrobić. –

+3

Jednym ze sposobów byłoby ponowne wykrycie kodu błędu z Fortran, sprawdzenie go po stronie Pythona i zgłoszenie wyjątku w przypadku wystąpienia błędu. –

Odpowiedz

1

f2py zawiera niektóre instrukcje, które można wykorzystać do zgłaszania wyjątków. Zobacz szczegóły tutaj:

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

W szczególności spojrzeć na callstatement który opisuje jak dodać f2py_success = 0 co spowoduje wyjątek.

Nie jestem pewien, czy to pomoże ci w debugowaniu wnętrza biblioteki fortranów, ale przynajmniej jest to początek.

1

Zasugerowałem społeczności numpy dodać dodatkowe "rozszerzenie" f2py (raise_python_exception), które umożliwia zdefiniowanie zmiennej łańcuchowej w Fortranie, która jeśli nie będzie pusta spowoduje, że Python podniesie wyjątek, gdy funkcja zwraca.

Więc w Fortran byś napisać coś takiego:

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 

I wywołana z Python zawartość zmiennej error_mesg służy jako treść wyjątkiem:

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. 

myślę, że to jest dość wygodny sposób na zgłaszanie wyjątków z Fortranu, ponieważ umożliwia łatwe zdefiniowanie komunikatu wyjątku. Włożyłem mój suggestion on github.

+0

Wartość 'error_mesg' jest niezdefiniowana w twoim przykładzie w innej gałęzi warunkowej. –

Powiązane problemy