如何使用编译后的Fortran扩展模块构建Python控制盘,而不需要用户';s系统?

如何使用编译后的Fortran扩展模块构建Python控制盘,而不需要用户';s系统?,python,dll,fortran,mingw,python-wheel,Python,Dll,Fortran,Mingw,Python Wheel,据我所知,通过wheels分发Python包的主要优点之一是,我可以以编译的形式包含扩展模块。然后,包的用户不需要拥有允许编译源代码的系统 现在我设法为我的包构建了一个轮子,其中包括一个Fortran扩展模块。我构建的计算机有Windows7 64和Python 3.6 为了让一切顺利进行,我遵循了这个非常有用的方法(非常感谢Michael Hirsch)。其中一个步骤是使用以下设置进行安装:体系结构:x86_64,线程:posix,异常:seh 然后,我在另一台测试机(Win10 64,Pyt

据我所知,通过wheels分发Python包的主要优点之一是,我可以以编译的形式包含扩展模块。然后,包的用户不需要拥有允许编译源代码的系统

现在我设法为我的包构建了一个轮子,其中包括一个Fortran扩展模块。我构建的计算机有Windows7 64和Python 3.6

为了让一切顺利进行,我遵循了这个非常有用的方法(非常感谢Michael Hirsch)。其中一个步骤是使用以下设置进行安装:体系结构:x86_64,线程:posix,异常:seh

然后,我在另一台测试机(Win10 64,Python 3.6)上安装了Python软件包:

D:\dist2>pip install SMUTHI-0.2.0a0-cp36-cp36m-win_amd64.whl
Processing d:\dist2\smuthi-0.2.0a0-cp36-cp36m-win_amd64.whl
Requirement already satisfied: scipy in c:\programdata\anaconda3\lib\site-packages (from SMUTHI==0.2.0a0)
Requirement already satisfied: sympy in c:\programdata\anaconda3\lib\site-packages (from SMUTHI==0.2.0a0)
Requirement already satisfied: argparse in c:\programdata\anaconda3\lib\site-packages (from SMUTHI==0.2.0a0)
Requirement already satisfied: numpy in c:\programdata\anaconda3\lib\site-packages (from SMUTHI==0.2.0a0)
Requirement already satisfied: matplotlib in c:\programdata\anaconda3\lib\site-packages (from SMUTHI==0.2.0a0)
Requirement already satisfied: pyyaml in c:\programdata\anaconda3\lib\site-packages (from SMUTHI==0.2.0a0)
Requirement already satisfied: six>=1.10 in c:\programdata\anaconda3\lib\site-packages (from matplotlib->SMUTHI==0.2.0a0)
Requirement already satisfied: python-dateutil in c:\programdata\anaconda3\lib\site-packages (from matplotlib->SMUTHI==0.2.0a0)
Requirement already satisfied: pytz in c:\programdata\anaconda3\lib\site-packages (from matplotlib->SMUTHI==0.2.0a0)
Requirement already satisfied: cycler>=0.10 in c:\programdata\anaconda3\lib\site-packages (from matplotlib->SMUTHI==0.2.0a0)
Requirement already satisfied: pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=1.5.6 in c:\programdata\anaconda3\lib\site-packages (from matplotlib->SMUTHI==0.2.0a0)
Installing collected packages: SMUTHI
Successfully installed SMUTHI-0.2.0a0
但是,当我启动程序的测试运行时,我遇到了以下错误:

D:\dist2>smuthi example_input.dat
Traceback (most recent call last):
  File "c:\programdata\anaconda3\lib\runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "c:\programdata\anaconda3\lib\runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "C:\ProgramData\Anaconda3\Scripts\smuthi.exe\__main__.py", line 5, in <module>
  File "c:\programdata\anaconda3\lib\site-packages\smuthi\__main__.py", line 4, in <module>
    import smuthi.read_input
  File "c:\programdata\anaconda3\lib\site-packages\smuthi\read_input.py", line 3, in <module>
    import smuthi.simulation
  File "c:\programdata\anaconda3\lib\site-packages\smuthi\simulation.py", line 8, in <module>
    import smuthi.t_matrix as tmt
  File "c:\programdata\anaconda3\lib\site-packages\smuthi\t_matrix.py", line 6, in <module>
    import smuthi.nfmds.t_matrix_axsym as nftaxs
  File "c:\programdata\anaconda3\lib\site-packages\smuthi\nfmds\t_matrix_axsym.py", line 11, in <module>
    import smuthi.nfmds.taxsym
ImportError: DLL load failed: Das angegebene Modul wurde nicht gefunden.
setup.py
的内容如下:

import setuptools
from numpy.distutils.core import Extension
from numpy.distutils.core import setup

setup(
   name="example",
   version="0.1",
   author="My Name",
   author_email="my@email.com",
   description="Example package to demonstrate wheel issue",
   packages=['example', 'example.extension_package'],
   ext_modules=[Extension('example.extension_package.fortran_hello',
                          ['example/extension_package/fortran_hello.f90'])],
)
import example.extension_package.fortran_hello
example.extension_package.fortran_hello.hello()
          
subroutine hello
print *,"Hello World!"
end subroutine hello
运行hello.py的
命令如下:

import setuptools
from numpy.distutils.core import Extension
from numpy.distutils.core import setup

setup(
   name="example",
   version="0.1",
   author="My Name",
   author_email="my@email.com",
   description="Example package to demonstrate wheel issue",
   packages=['example', 'example.extension_package'],
   ext_modules=[Extension('example.extension_package.fortran_hello',
                          ['example/extension_package/fortran_hello.f90'])],
)
import example.extension_package.fortran_hello
example.extension_package.fortran_hello.hello()
          
subroutine hello
print *,"Hello World!"
end subroutine hello
fortran_hello.f90
的内容如下:

import setuptools
from numpy.distutils.core import Extension
from numpy.distutils.core import setup

setup(
   name="example",
   version="0.1",
   author="My Name",
   author_email="my@email.com",
   description="Example package to demonstrate wheel issue",
   packages=['example', 'example.extension_package'],
   ext_modules=[Extension('example.extension_package.fortran_hello',
                          ['example/extension_package/fortran_hello.f90'])],
)
import example.extension_package.fortran_hello
example.extension_package.fortran_hello.hello()
          
subroutine hello
print *,"Hello World!"
end subroutine hello
轮子的创造 我运行了
python setup.py bdist\u wheel
,生成了文件
example-0.1-cp36-cp36m-win\u amd64.whl

使用正确的MinGW版本在机器上安装软件包 这是应该的

在没有正确MinGW版本的机器上安装软件包 为了重现错误,我将测试机上的MinGW文件夹重命名为其他名称,然后:

D:\dist>pip install example-0.1-cp36-cp36m-win_amd64.whl
Processing d:\dist\example-0.1-cp36-cp36m-win_amd64.whl
Installing collected packages: example
Successfully installed example-0.1

D:\dist>python
Python 3.6.0 |Anaconda 4.3.1 (64-bit)| (default, Dec 23 2016, 11:57:41) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import example.run_hello
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\ProgramData\Anaconda3\lib\site-packages\example\run_hello.py", line 1, in <module>
    import example.extension_package.fortran_hello
ImportError: DLL load failed: Das angegebene Modul wurde nicht gefunden.
D:\dist>pip安装示例-0.1-cp36-cp36m-win\u amd64.whl
处理d:\dist\example-0.1-cp36-cp36m-win\u amd64.whl
安装收集的软件包:示例
已成功安装示例-0.1
D:\dist>python
win32上的Python 3.6.0 | Anaconda 4.3.1(64位)|(默认值,2016年12月23日,11:57:41)[MSC v.1900 64位(AMD64)]
有关详细信息,请键入“帮助”、“版权”、“信用证”或“许可证”。
>>>导入example.run\u hello
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“C:\ProgramData\Anaconda3\lib\site packages\example\run\u hello.py”,第1行,在
导入example.extension\u package.fortran\u hello
导入错误:DLL加载失败:Das angegebene module wurde nicht gefunden。

我最近遇到了这个问题,我编写了自己的f2py构建工具链,分别编译和链接所有组件。脚本正在自动查找或安装所需的编译器(如果路径上尚未找到)。对于gfortran工具不在路径上,但在机器上存在的情况,我能够将正确的环境变量注入到
os.environ
,并使用
Popen
和环境变量集生成编译器调用,以便pyd能够编译。但是在python实例之外,环境变量对于pyd的运行是不正确的,即使在编译pyd但没有正确路径设置的同一台计算机上,我也会遇到相同的
DLL加载失败
错误

因此,由于我单独编译所有步骤,仅使用f2py生成f和c包装器,因此我只需将
-static-static libgfortran-static libgcc
添加到我的链接步骤中,这会导致pyd包含在没有正确环境变量的机器上运行所需的库

使用numpy.distutils实现同样的功能是可能的(多亏了):

我将上述内容放在一个文件
test.py
中,并使用
python test.py build\u ext--inplace--compiler=mingw32--fcompiler=gnu95-f

作为比较,有一个明确的结论。使用dependency walker检查pyd显示该pyd依赖于
libgfortran-4.dll
,而额外的标志生成了一个pyd。在我的例子中,在添加静态标志后,没有正确环境变量的机器能够运行pyds,我怀疑这种情况与您的情况类似,因为对libgfortran的依赖被删除


希望有帮助!我的第一篇SO帖子..

我可以确认创建pyd文件中描述的步骤可以从未安装MinGW的机器导入。这真的很有帮助

为了创建二进制控制盘,我执行以下操作:

  • 按照中描述的步骤生成静态链接的pyd文件
  • 然后运行
    python setup.py bdist\u wheel
  • 对于第二步,我关闭pyd文件的编译(例如,通过从
    setup()
    调用中删除
    ext\u modules
    关键字),因为我希望使用在第一步中创建的pyd文件(而不是新创建的,可能不是静态链接的)


    我不知道这是否有意义,但它似乎有效…

    您以何种方式编译和连接Fortran模块?或还是别的什么?一个简单的例子()会很有帮助。谢谢你的建议-我已经相应地更新了这个问题。我希望你的FORTRAN扩展没有将一些必需的DLL与之链接。这就解释了为什么它在安装正确的MinGW版本(包括缺少的dll)后仍能工作。令人困惑的是,错误消息表示未找到DLL,而实际上它找不到未包含的其他DLL。你用过gfortran吗?因为在使用gfortran时,很难将所需的DLL与FORTRAN扩展链接起来(有人知道如何正式链接吗?。@马克,谢谢你的提示。是的,我在用gfortran。您是否建议使用其他编译器?我从您的回复中确认您尚未解决此问题?(如有,请在此张贴)。不管怎样,我遇到了同样的问题。gfortran中没有标准选项来链接所需的DLL或syslibs(Mac),至少在我尝试时没有。因此,你必须对gfortran进行一些黑客攻击才能做到这一点。让我看看我是怎么做到的。关于你的问题:我怀疑(或至少希望)这可能是eas