f2py: выставление параметров из "используемых" модулей
Я предполагаю, что этот вопрос был где-то рассмотрен, но я потратил слишком много времени на поиски ответа, в том числе на копание в исходном коде. Я попытался поставить проблему в первом абзаце. Остальное показывает базовый пример проблемы.
Я пытаюсь скомпилировать модуль, который содержит 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
Просто чтобы проиллюстрировать это b
определяется правильно в test2 с точки зрения fortran, следующий код использует test2 и печатает оба b
а также 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, run_test может быть импортирован в python и работает должным образом:
In [1]: import run_test
In [2]: run_test.run_test()
a = 1
b = 2
Любая помощь с этим вопросом будет принята с благодарностью.
TL; DR: когда модуль F90, который содержит USE
скомпилирован с помощью f2py, он не отображает параметры, которые определены в "используемом" модуле как атрибуты в Python.
1 ответ
Я нашел временное решение этой проблемы, но оно не является оптимальным. Я буду продолжать работать с исходным кодом f2py, чтобы лучше понять его и устранить проблему в самом коде. До тех пор это мое решение, которое вдохновлялось комментариями Chatcannon к проблеме, которую я разместил на github nympy.
Существует несколько способов решения этой проблемы с временной точки зрения, включая несколько способов изменения файлов.pyf. Я не хочу изменять файлы.pyf, так как они становятся очень громоздкими как часть большого пакета. Чтобы избежать этого, я добавил директивы f2py в мой источник f90.
Взяв пример из моего первоначального вопроса:
MODULE test
INTEGER, PARAMETER :: a = 1
END MODULE test
MODULE test2
USE test
INTEGER, PARAMETER :: b = 2
END MODULE test2
просто добавьте директиву f2py в test2, чтобы показать 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