Вопрос Длина имени файла легко расправился с: вы делаете имя файла: character(len_filename):: filename
, имеют len_filename
в качестве параметра фортрановской функции и использовать f2py intent(hide)
, чтобы скрыть его от вашего Python (см. Код ниже).
Ваша проблема не в том, чтобы проходить в nx
и ny
более сложна и по сути является проблемой возврата выделенного массива из f2py. Я вижу два метода, для которых требуется небольшая и очень легкая оболочка Python, чтобы дать вам приятный интерфейс.
На самом деле я не рассматривал проблему чтения файла csv - я только что сгенерировал и возвратил некоторые фиктивные данные. Я предполагаю, что у вас есть хорошая реализация для этого.
Метод 1: Уровень модуля размещаемых массивов
Это кажется довольно стандартный метод - я нашел в least one newsgroup post рекомендовать это. Вы по существу имеете распределяемую глобальную переменную, инициализируете ее до нужного размера и записываете в нее.
module mod
real, allocatable, dimension(:,:) :: genfromtxt_output
contains
subroutine genfromtxt_v1(filename, len_filename)
implicit none
character(len_filename), intent(in):: filename
integer, intent(in) :: len_filename
!f2py intent(hide) :: len_filename
integer :: row, col
! for the sake of a quick demo, assume 5*6
! and make it all 2
if (allocated(genfromtxt_output)) deallocate(genfromtxt_output)
allocate(genfromtxt_output(1:5,1:6))
do row = 1,5
do col = 1,6
genfromtxt_output(row,col) = 2
end do
end do
end subroutine genfromtxt_v1
end module mod
Короткий Python обертка будет выглядеть следующим образом:
import _genfromtxt
def genfromtxt_v1(filename):
_genfromtxt.mod.genfromtxt_v1(filename)
return _genfromtxt.mod.genfromtxt_output.copy()
# copy is needed, otherwise subsequent calls overwrite the data
Основная проблема с этим состоит в том, что он не будет потокобезопасным: если два потока Python называть genfromtxt_v1
в очень похожие разы данных может быть перезаписано, прежде чем вы изменили его.
Метод 2: Python функция обратного вызова, которая сохраняет данные
Это немного сложнее, и ужасающим хак моего собственного изобретения. Вы передаете свой массив функции обратного вызова, которая затем сохраняет ее. Fortran код выглядит следующим образом:
subroutine genfromtxt_v2(filename,len_filename,callable)
implicit none
character(len_filename), intent(in):: filename
integer, intent(in) :: len_filename
!f2py intent(hide) :: len_filename
external callable
real, allocatable, dimension(:,:) :: result
integer :: row, col
integer :: rows,cols
! for the sake of a quick demo, assume 5*6
! and make it all 2
rows = 5
cols = 6
allocate(result(1:rows,1:cols))
do row = 1,rows
do col = 1,cols
result(row,col) = 2
end do
end do
call callable(result,rows,cols)
deallocate(result)
end subroutine genfromtxt_v2
Затем нужно произвести «подписи файла» с f2py -m _genfromtxt -h _genfromtxt.pyf genfromtxt.f90
(при условии, genfromtxt.f90
это файл с Fortran кода). Затем измените «подпрограммы пользователя блок», чтобы уточнить подпись обратного вызова:
python module genfromtxt_v2__user__routines
interface genfromtxt_v2_user_interface
subroutine callable(result,rows,cols)
real, dimension(rows,cols) :: result
integer :: rows
integer :: cols
end subroutine callable
end interface genfromtxt_v2_user_interface
end python module genfromtxt_v2__user__routines
(т.е. вы указываете размеры). Остальная часть файла остается неизменной. Compile с f2py -c genfromtxt.f90 _genfromtxt.pyf
Небольшой Python обертка
import _genfromtxt
def genfromtxt_v2(filename):
class SaveArrayCallable(object):
def __call__(self,array):
self.array = array.copy() # needed to avoid data corruption
f = SaveArrayCallable()
_genfromtxt.genfromtxt_v2(filename,f)
return f.array
Я думаю это должно быть поточно: хотя я думаю, что функции обратного вызова Python реализованы как глобальные переменные, но по умолчанию f2py не освобождает GIL, поэтому код Python не может быть запущен между установленным глобальным и выполняемым обратным вызовом. Я сомневаюсь, что вы заботитесь о безопасности потоков для этого приложения, хотя ...
Читатель Pandas csv должен быть немного быстрее, чем 'numpy'. – hpaulj