我正在尝试为我的领域中的一些流行的Fortran代码进行python包分发.我希望它对setup.py文件使用最标准的方法.相关的qustion有助于学习如何包装Fortran扩展.
当使用这种方法,我混合时发现一些容易混淆的行为setuptools和numpy.distutils.将两者混合是不好的做法吗?截至2015年,似乎最好setuptools尽可能多地使用.
但是,我想以Fortran一种兼容的方式构建扩展numpy. 所以我想从中导入numpy.distutils以获取Extension和setup.
我使用以下基本方法:
from setuptools.command.develop import develop
from numpy.distutils.core import Extension, setup
ext_modules=[Extension("my_package.fortran_mod", sources=['src/fortran_mod.f'])]
class MyDevelop(develop):
def run(self):
my_script()
develop.run(self)
setup(
...
ext_modules=ext_modules,
cmdclass={'develop':MyDevelop})
Run Code Online (Sandbox Code Playgroud)
这似乎有效,但我有疑问.
setuptools和一般是好的做法numpy.distribute吗?setuptools先进口吗?numpy?也许甚至有一些讨论Fortran扩展?https://www.youtube.com/watch?v=R4yB-8tB0J0
http://www.fortran90.org/src/best-practices.html#interfacing-with-python
我想为python包创建一个setup.py脚本,其中包含几个依赖于cython和f2py的子模块.我试图使用setuptools和numpy.distutils,但到目前为止失败了:
我可以使用setuptools编译我的cython扩展(并为包的其余部分创建一个安装).但是,我无法弄清楚如何使用setuptools来生成f2py扩展.经过广泛的搜索,我只发现了像这样的旧消息,声明必须使用numpy.distutils编译f2py模块.
我可以使用numpy.distutils编译我的f2py扩展(并为包的其余部分创建安装).但是,我一直无法弄清楚如何让numpy.distutils编译我的cython扩展,因为它总是尝试使用pyrex来编译它(我使用的是特定于cython的扩展).我已经做了一个搜索来弄清楚如何为cython文件获取numpy.distutils - 至少在一年前 - 他们建议将一个猴子补丁应用于numpy.distutils.似乎应用这样的猴子补丁也限制了可以传递给Cython的选项.
我的问题是:为依赖于f2py和cython的软件包编写setup.py脚本的推荐方法是什么?是否应用numpy.distutils补丁真的要走了吗?
我认为这个问题已在某个地方得到解决,但我花了大量时间寻找答案,包括深入研究源代码.我试图把问题放在第一段.其余部分显示了问题的基本示例.
我正在尝试编译一个包含USE指向另一个更通用的模块的语句的模块.我更希望将使用过的模块保持独立,以便可以将它作为一组常规设置用于多个"包"中.当我使用f2py编译这两个模块时,一切都像fortran那样宣传,但是从python那边USE看起来似乎被忽略了.如果我允许f2py生成签名文件,则该文件包含USE适当的语句,但如果我完成编译并从结果库导入,则使用模块中的参数在包含use语句的模块中不可用.以下是说明情况的两个模块:
MODULE test
INTEGER, PARAMETER :: a = 1
END MODULE test
MODULE test2
USE test
INTEGER, PARAMETER :: b = 2
END MODULE test2
Run Code Online (Sandbox Code Playgroud)
为了显示我跑的中间步骤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 …Run Code Online (Sandbox Code Playgroud) 我正在开发一个包,它需要来自LAPACK Fortran库的dgtsv子例程的 Python绑定.目前,我正在分发Fortran源文件,dgtsv.f以及我的Python代码,并使用numpy.distutils它自动包装并将其编译成_gtsv.so可从Python调用的共享库.
这是我的setup.py文件目前的样子:
from numpy.distutils.core import setup, Extension, build_ext
import os
fortran_sources = ["dgtsv.f"]
gtsv = Extension(
name="pyfnnd._gtsv",
sources=[os.path.join("pyfnnd", "LAPACK", ff) for ff in fortran_sources],
extra_link_args=['-llapack']
)
setup(
name='pyfnnd',
py_modules=['_fnndeconv', 'demo', '_tridiag_solvers'],
cmdclass={'build_ext': build_ext.build_ext},
ext_modules=[gtsv],
)
Run Code Online (Sandbox Code Playgroud)
请注意,为了实际使用_gtsv.so,我仍然需要链接到预先存在的LAPACK共享库(extra_link_args=['-llapack']).由于这个库应该已经包含dgtsv子例程,在我看来,将函数包装在现有的共享库中更简洁,而不必分发实际的Fortran源.
但是,我从未遇到任何使用F2PY来包装作为共享库的一部分的函数而不仅仅是原始Fortran源代码的示例.这可能吗?
我想使用docstring或类似的东西记录我的fortran例程,这些例程可以与python help命令一起使用.由f2py生成的自动生成的文档字符串是不够的,我需要添加更多细节,就像我们使用python函数docstring一样.
在我的想法中,它应该看起来像:
mymod.f:
subroutine foo()
! This is my function
end subroutine
Run Code Online (Sandbox Code Playgroud)
并在python会话中:
>>> import mymod
>>> help(mymod.foo)
Run Code Online (Sandbox Code Playgroud) 我正在尝试使用Numpy的f2py.py脚本从Fortran源构建Python扩展.我正在按照http://www.scipy.org/F2PY_Windows(网络存档)中的步骤操作.我的系统是Windows 7 64位,我主要使用Python 2.7.3 [MSC v.1500 64位(AMD64)].我有Numpy-MKL 1.7.1,来自http://www.lfd.uci.edu/~gohlke/pythonlibs/#numpy
这是我尝试过的:
cmd.exeshell,并编辑我解压缩GCC编译器的路径,即:
set PATH=%PATH%;c:\gnu\mingw64\binset C_INCLUDE_PATH=C:\gnu\mingw64\includef2py.py使用此命令尝试构建:
C:\Python27\python.exe C:\Python27\Scripts\f2py.py -c --fcompiler=gnu95 --compiler=mingw32 -lmsvcr90 -m foo foo.f90
输出是(去除噪声线<--snip-->):
running build
<--snip-->
Reading fortran codes...
Reading file 'foo.f90' (format:free)
Post-processing...
Block: foo
Block: hello
Post-processing (stage 2)...
Building modules...
Building module "foo"...
Constructing wrapper function "hello"...
hello()
Wrote C/API module "foo" to file "c:\users\mtoews\appdata\local\temp\tmpjr6qop\src.win-amd64-2.7\foomodule.c"
adding 'c:\users\mtoews\appdata\local\temp\tmpjr6qop\src.win-amd64-2.7\fortranobject.c' to sources.
adding …Run Code Online (Sandbox Code Playgroud) 免责声明:我对使用distutils的python包装非常陌生.到目前为止,我只是把所有东西都藏进了模块,手工打包并在此基础上开发.我以前从未写过setup.py文件.
我有一个Fortran模块,我想在我的python代码中使用numpy.我认为最好的方法是f2py,因为它包含在numpy中.为了自动化构建过程,我想使用distutils和相应的numpy增强功能,其中包括f2py包装器的便捷功能.
我不明白我应该如何组织我的文件,以及如何包含我的测试套件.
我想要的是./setup.py用于构建,安装,测试和开发的可能性.
我的目录结构如下:
volterra
??? setup.py
??? volterra
??? __init__.py
??? integral.f90
??? test
? ??? __init__.py
? ??? test_volterra.py
??? volterra.f90
Run Code Online (Sandbox Code Playgroud)
该setup.py文件包含:
def configuration(parent_package='', top_path=None):
from numpy.distutils.misc_util import Configuration
config = Configuration('volterra', parent_package, top_path)
config.add_extension('_volterra',
sources=['volterra/integral.f90', 'volterra/volterra.f90'])
return config
if __name__ == '__main__':
from numpy.distutils.core import setup
setup(**configuration(top_path='').todict())
Run Code Online (Sandbox Code Playgroud)
跑完后./setup.py build我得到了.
build/lib.linux-x86_64-2.7/
??? volterra
??? _volterra.so
Run Code Online (Sandbox Code Playgroud)
其中既不包含__init__.py文件也不包含测试.
volterra/integral.f90)我不能给出一个参数说,找东西volterra/?的top_path,并且package_dir参数没有做的伎俩. …我将Python加速器(Numba,Cython,f2py)与简单的For循环和Numpy的einsum进行比较以解决特定问题(见下文).到目前为止,Numpy是这个问题最快的因素(速度提高了6倍),但是如果我应该尝试额外的优化,或者我做错了什么,我想要一些反馈.这个简单的代码基于一个更大的代码,它有许多这些einsum调用,但没有明确的for循环.我正在检查这些加速器是否可以做得更好.
在Mac OS X Yosemite上使用Python 2.7.9完成计时,安装了gcc-5.3.0(--with-fortran --without-multilib)来自Homebrew.也做了%timeit电话; 这些单一的通话时间相当准确.
In [1]: %run -i test_numba.py
test_numpy: 0.0805640220642
Matches Numpy output: True
test_dumb: 1.43043899536
Matches Numpy output: True
test_numba: 0.464295864105
Matches Numpy output: True
test_cython: 0.627640008926
Matches Numpy output: True
test_f2py: 5.01890516281
Matches Numpy output: True
test_f2py_order: 2.31424307823
Matches Numpy output: True
test_f2py_reorder: 0.507861852646
Matches Numpy output: True
Run Code Online (Sandbox Code Playgroud)
主要代码:
import numpy as np
import numba
import time
import test_f2py as tf2py
import pyximport
pyximport.install(setup_args={'include_dirs':np.get_include()})
import test_cython as tcyth
def test_dumb(f,b):
fnew = np.empty((f.shape[1],f.shape[2])) …Run Code Online (Sandbox Code Playgroud) 我有一个Fortran程序,并希望在python中为多个文件执行它.我有2000个输入文件,但在我的Fortran代码中,我一次只能运行一个文件.我应该如何在python中调用Fortran程序?
我的剧本:
import subprocess
import glob
input = glob.glob('C:/Users/Vishnu/Desktop/Fortran_Program_Rum/*.txt')
output = glob.glob('C:/Users/Vishnu/Desktop/Fortran_Program_Rum/Output/')
f = open("output", "w")
for i in input:
subprocess.Popen(["FORTRAN ~/C:/Users/Vishnu/Desktop/Fortran_Program_Rum/phase1.f", "--domain "+i])
f.write(i)
Run Code Online (Sandbox Code Playgroud)
错误:
runfile('C:/Users/Vishnu/Desktop/test_fn/test.py', wdir='C:/Users/Vishnu/Desktop/test_fn')
Traceback (most recent call last):
File "<ipython-input-3-f8f378816004>", line 1, in <module>
runfile('C:/Users/Vishnu/Desktop/test_fn/test.py', wdir='C:/Users/Vishnu/Desktop/test_fn')
File "C:\Users\Vishnu\Anaconda3\lib\site-packages\spyder\utils\site\sitecustomize.py", line 866, in runfile
execfile(filename, namespace)
File "C:\Users\Vishnu\Anaconda3\lib\site-packages\spyder\utils\site\sitecustomize.py", line 102, in execfile
exec(compile(f.read(), filename, 'exec'), namespace)
File "C:/Users/Vishnu/Desktop/test_fn/test.py", line 30, in <module>
subprocess.Popen(["FORTRAN ~/C:/Users/Vishnu/Desktop/Fortran_Program_Rum/phase1.f", "--domain "+i])
File "C:\Users\Vishnu\Anaconda3\lib\subprocess.py", line 707, in __init__
restore_signals, start_new_session)
File "C:\Users\Vishnu\Anaconda3\lib\subprocess.py", line …Run Code Online (Sandbox Code Playgroud) 我可以将一维数组传递给python,如下所示.我想知道我是否可以通过使用ctypes,numpy将c ++双指针数组传递给python.
TEST.CPP:
#include <stdio.h>
extern "C" void cfun(const void * indatav, int rowcount, int colcount, void * outdatav);
void cfun(const void * indatav, int rowcount, int colcount, void * outdatav) {
//void cfun(const double * indata, int rowcount, int colcount, double * outdata) {
const double * indata = (double *) indatav;
double * outdata = (double *) outdatav;
int i;
puts("Here we go!");
for (i = 0; i < rowcount * colcount; ++i) {
outdata[i] = indata[i] * …Run Code Online (Sandbox Code Playgroud)