F2py: отображение параметров из "используемых" модулей - программирование
Подтвердить что ты не робот

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" содержит "тест использования":

!    -*- 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.

4b9b3361

Ответ 1

Я нашел временное решение этой проблемы, но это не оптимально. Я буду продолжать работать через источник f2py, чтобы я мог лучше понять его и исправить проблему в самом коде. До тех пор это мое решение, которое было вдохновлено комментарием chatcannon на вопрос, который я отправил в nympy github.

Существует несколько способов решения этой проблемы с временной точки зрения, включая пару способов изменения файлов .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