将f2py Python模块从numpy.distutils迁移到scikit-build-core遇阻
Tsyganenko模块迁移至scikit-build-core后导入失败问题解决
原numpy.distutils配置(setup.py)
from numpy.distutils.core import Extension, setup ext = Extension('geopack', sources=['src/tsyganenko/geopack_py.pyf', 'src/tsyganenko/geopack_py.f', 'src/tsyganenko/T96.f', 'src/tsyganenko/T02.f']) with open("README.md", "r", encoding="utf-8") as f: long_description = f.read() setup(author="John Coxon and Sebastien de Larquier", author_email="work@johncoxon.co.uk", classifiers=[ "Development Status :: 4 - Beta", "Intended Audience :: Science/Research", "Natural Language :: English", "Programming Language :: Python/Fortran" ], description="A wrapper to call GEOPACK routines in Python.", ext_modules=[ext], install_requires=[ "numpy", "matplotlib", "pandas" ], keywords=['Scientific/Space'], long_description=long_description, long_description_content_type="text/markdown", name="Tsyganenko", package_dir={"": "src"}, packages=setuptools.find_packages(where="src"), python_requires=">=3.9", url="https://github.com/johncoxon/tsyganenko", version="2020.1", )
迁移后的scikit-build-core配置
pyproject.toml
[build-system] requires = ["scikit-build-core", "numpy"] build-backend = "scikit_build_core.build" [project] name = "Tsyganenko" version = "2020.2" dependencies = ["numpy"] [tool.scikit-build] ninja.version = ">=1.10" cmake.version = ">=3.17.2" [tool.setuptools.packages.find] where = ["src"]
CMakeLists.txt
cmake_minimum_required(VERSION 3.17.2...3.29) project(${SKBUILD_PROJECT_NAME} LANGUAGES C Fortran) find_package( Python COMPONENTS Interpreter Development.Module NumPy REQUIRED) # F2PY headers execute_process( COMMAND "${PYTHON_EXECUTABLE}" -c "import numpy.f2py; print(numpy.f2py.get_include())" OUTPUT_VARIABLE F2PY_INCLUDE_DIR OUTPUT_STRIP_TRAILING_WHITESPACE) add_library(fortranobject OBJECT "${F2PY_INCLUDE_DIR}/fortranobject.c") target_link_libraries(fortranobject PUBLIC Python::NumPy) target_include_directories(fortranobject PUBLIC "${F2PY_INCLUDE_DIR}") set_property(TARGET fortranobject PROPERTY POSITION_INDEPENDENT_CODE ON) add_custom_command( OUTPUT geopack_pymodule.c geopack_py-f2pywrappers.f DEPENDS src/tsyganenko/geopack_py.f VERBATIM COMMAND "${Python_EXECUTABLE}" -m numpy.f2py "${CMAKE_CURRENT_SOURCE_DIR}/src/tsyganenko/geopack_py.f" -m geopack_py --lower) python_add_library( geopack_py MODULE "${CMAKE_CURRENT_BINARY_DIR}/geopack_pymodule.c" "${CMAKE_CURRENT_BINARY_DIR}/geopack_py-f2pywrappers.f" "${CMAKE_CURRENT_SOURCE_DIR}/src/tsyganenko/geopack_py.f" WITH_SOABI) target_link_libraries(geopack_py PRIVATE fortranobject) install(TARGETS geopack_py DESTINATION .)
导入错误信息
In [1]: import geopack_py --------------------------------------------------------------------------- ImportError Traceback (most recent call last) Cell In[1], line 1 ----> 1 import geopack_py ImportError: dlopen(/opt/homebrew/Caskroom/mambaforge/base/envs/test/lib/python3.12/site-packages/geopack_py.cpython-312-darwin.so, 0x0002): symbol not found in flat namespace '_t01_01_'
问题原因
错误提示的_t01_01_符号来自T02.f文件,但当前CMake配置未将T96.f和T02.f纳入编译流程,同时未正确使用原setup.py中的geopack_py.pyf接口定义文件,导致F2PY生成的wrapper无法找到依赖的Fortran子程序。
解决方案
1. 修正CMakeLists.txt,纳入所有Fortran源文件并使用pyf接口
修改add_custom_command和python_add_library部分,确保包含geopack_py.pyf、T96.f和T02.f:
# 替换原有add_custom_command add_custom_command( OUTPUT geopack_pymodule.c geopack_py-f2pywrappers.f DEPENDS src/tsyganenko/geopack_py.pyf src/tsyganenko/geopack_py.f src/tsyganenko/T96.f src/tsyganenko/T02.f VERBATIM COMMAND "${Python_EXECUTABLE}" -m numpy.f2py "${CMAKE_CURRENT_SOURCE_DIR}/src/tsyganenko/geopack_py.pyf" "${CMAKE_CURRENT_SOURCE_DIR}/src/tsyganenko/geopack_py.f" "${CMAKE_CURRENT_SOURCE_DIR}/src/tsyganenko/T96.f" "${CMAKE_CURRENT_SOURCE_DIR}/src/tsyganenko/T02.f" -m geopack_py --lower) # 替换原有python_add_library python_add_library( geopack_py MODULE "${CMAKE_CURRENT_BINARY_DIR}/geopack_pymodule.c" "${CMAKE_CURRENT_BINARY_DIR}/geopack_py-f2pywrappers.f" "${CMAKE_CURRENT_SOURCE_DIR}/src/tsyganenko/geopack_py.f" "${CMAKE_CURRENT_SOURCE_DIR}/src/tsyganenko/T96.f" "${CMAKE_CURRENT_SOURCE_DIR}/src/tsyganenko/T02.f" WITH_SOABI) target_link_libraries(geopack_py PRIVATE fortranobject)
2. 补全pyproject.toml中的项目配置
原setup.py中的依赖、作者、分类器等信息需要同步到pyproject.toml:
[project] name = "Tsyganenko" version = "2020.2" authors = [ { name = "John Coxon and Sebastien de Larquier", email = "work@johncoxon.co.uk" } ] description = "A wrapper to call GEOPACK routines in Python." readme = "README.md" requires-python = ">=3.9" classifiers = [ "Development Status :: 4 - Beta", "Intended Audience :: Science/Research", "Natural Language :: English", "Programming Language :: Python", "Programming Language :: Fortran" ] keywords = ["Scientific", "Space"] dependencies = ["numpy", "matplotlib", "pandas"]
3. 验证安装
重新执行安装命令:
pip install . --no-build-isolation
安装完成后即可正常导入geopack_py模块。
内容的提问来源于stack exchange,提问作者John Coxon
相关产品推荐
相关产品推荐

