2013-10-10 14 views
9

はじめに

免責事項:distutilsを使用したPythonパッケージングにはとても新しいです。これまではすべてをモジュールに隠し、手動でパッケージ化し、その上に開発しました。以前はsetup.pyというファイルを書いたことはありませんでした。numpyとテストスイートパッケージ

私はnumpyで私のPythonコードで使用したいFortranモジュールを持っています。私はnumpyに含まれているので、それを行う最善の方法はf2pyであると考えました。ビルドプロセスを自動化するために、私はdistutilsとそれに対応するnumpy拡張を使用したいと思います。これにはf2pyラッパーの便利な機能が含まれています。

ファイルをどのように整理し、テストスイートをどのように組み込むべきか分かりません。

ビルド、インストール、テスト、および開発に./setup.pyを使用することができます。次のように

私のディレクトリ構造はなります私が手./setup.py buildを実行した後

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()) 

volterra 
├── setup.py 
└── volterra 
    ├── __init__.py 
    ├── integral.f90 
    ├── test 
    │   ├── __init__.py 
    │   └── test_volterra.py 
    └── volterra.f90 

そしてsetup.pyファイルには、これが含まれています。

build/lib.linux-x86_64-2.7/ 
└── volterra 
    └── _volterra.so 

__init__.pyファイルもテストも含まれていません。

質問

  • は延長のすべての単一のソースファイルへのパスを追加することが本当に必要ですか? (つまり、volterra/integral.f90volterra/のものを探すというパラメータを与えることはできませんか? top_pathpackage_dirのパラメータでは、このトリックは行われませんでした。
  • 現在、__init__.pyファイルはビルドに含まれていません。何故ですか?
  • この設定でテストを実行するにはどうすればよいですか?
  • このような環境で開発するためのベストワークフローは何ですか?私はをインストールしたいとは思わない私は毎回変更するために私のパッケージをインストールします。いくつかの拡張モジュールをコンパイルする必要があるときに、どのようにソースディレクトリで開発を行うのですか?
+0

fortranファイルを含めるには、MANIFEST.inファイル(http://docs.python.org/3/distutils/sourcedist.html#manifest)に「include * .f90」のようなものを含めることができます – rtrwalker

+0

しかし、特に'__init __。py'ファイルはパッケージの一部であり、マニフェストでこれを手動で指定しなくても自動的にインクルードする必要があります。さもなければパッケージを含んでいなくても自動マニフェスト生成のポイントは何ですか? – Lemming

+0

私はすべての単一のソースファイルを含める必要があると信じています。私は家から今夜確認しようとします(以前の仕事でNumPyとF2Pyで遊んでいました)。 –

答えて

2

は私の作品setup.pyです:

# pkg - A fancy software package 
# Copyright (C) 2013 author (email) 
# 
# This program is free software: you can redistribute it and/or modify 
# it under the terms of the GNU General Public License as published by 
# the Free Software Foundation, either version 3 of the License, or 
# (at your option) any later version. 
# 
# This program is distributed in the hope that it will be useful, 
# but WITHOUT ANY WARRANTY; without even the implied warranty of 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
# GNU General Public License for more details. 
# 
# You should have received a copy of the GNU General Public License 
# along with this program. If not, see http://www.gnu.org/licenses/gpl.html. 
"""pkg: a software suite for 

Hey look at me I'm a long description 
But how long am I? 

""" 

from __future__ import division, print_function 

#ideas for setup/f2py came from: 
# -numpy setup.py: https://github.com/numpy/numpy/blob/master/setup.py 2013-11-07 
# -winpython setup.py: http://code.google.com/p/winpython/source/browse/setup.py 2013-11-07 
# -needing to use 
#  import setuptools; from numpy.distutils.core import setup, Extension: 
#  http://comments.gmane.org/gmane.comp.python.f2py.user/707 2013-11-07 
# -wrapping FORTRAN code with f2py: http://www2-pcmdi.llnl.gov/cdat/tutorials/f2py-wrapping-fortran-code 2013-11-07 
# -numpy disutils: http://docs.scipy.org/doc/numpy/reference/distutils.html 2013-11-07 
# -manifest files in disutils: 
#  'distutils doesn't properly update MANIFEST. when the contents of directories change.' 
#  https://github.com/numpy/numpy/blob/master/setup.py   
# -if things are not woring try deleting build, sdist, egg directories and try again: 
#  https://stackoverflow.com/a/9982133/2530083 2013-11-07 
# -getting fortran extensions to be installed in their appropriate sub package 
#  i.e. "my_ext = Extension(name = 'my_pack._fortran', sources = ['my_pack/code.f90'])" 
#  Note that sources is a list even if one file: 
#  http://numpy-discussion.10968.n7.nabble.com/f2py-and-setup-py-how-can-I-specify-where-the-so-file-goes-tp34490p34497.html 2013-11-07 
# -install fortran source files into their appropriate sub-package 
#  i.e. "package_data={'': ['*.f95','*.f90']}# Note it's a dict and list": 
#  https://stackoverflow.com/a/19373744/2530083 2013-11-07 
# -Chapter 9 Fortran Programming with NumPy Arrays: 
#  Langtangen, Hans Petter. 2013. Python Scripting for Computational Science. 3rd edition. Springer. 
# -Hitchhikers guide to packaging : 
#  http://guide.python-distribute.org/ 
# -Python Packaging: Hate, hate, hate everywhere : 
#  http://lucumr.pocoo.org/2012/6/22/hate-hate-hate-everywhere/ 
# -How To Package Your Python Code: 
#  http://www.scotttorborg.com/python-packaging/ 
# -install testing requirements: 
#  https://stackoverflow.com/a/7747140/2530083 2013-11-07 

import setuptools 
from numpy.distutils.core import setup, Extension 
import os 
import os.path as osp 

def readme(filename='README.rst'): 
    with open('README.rst') as f: 
     text=f.read() 
    f.close() 
    return text 

def get_package_data(name, extlist): 
    """Return data files for package *name* with extensions in *extlist*""" 
    #modified slightly from taken from http://code.google.com/p/winpython/source/browse/setup.py 2013-11-7 
    flist = [] 
    # Workaround to replace os.path.relpath (not available until Python 2.6): 
    offset = len(name)+len(os.pathsep) 
    for dirpath, _dirnames, filenames in os.walk(name): 
     for fname in filenames:    
      if not fname.startswith('.') and osp.splitext(fname)[1] in extlist: 
#    flist.append(osp.join(dirpath, fname[offset:])) 
       flist.append(osp.join(dirpath, fname)) 
    return flist 

DOCLINES = __doc__.split("\n") 
CLASSIFIERS = """\ 
Development Status :: 1 - Planning 
License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+) 
Programming Language :: Python :: 2.7 
Topic :: Scientific/Engineering 
""" 

NAME = 'pkg' 
MAINTAINER = "me" 
MAINTAINER_EMAIL = "[email protected]" 
DESCRIPTION = DOCLINES[0] 
LONG_DESCRIPTION = "\n".join(DOCLINES[2:])#readme('readme.rst') 
URL = "http://meeeee.mmemem" 
DOWNLOAD_URL = "https://github.com/rtrwalker/geotecha.git" 
LICENSE = 'GNU General Public License v3 or later (GPLv3+)' 
CLASSIFIERS = [_f for _f in CLASSIFIERS.split('\n') if _f] 
KEYWORDS='' 
AUTHOR = "me" 
AUTHOR_EMAIL = "me.com" 
PLATFORMS = ["Windows"]#, "Linux", "Solaris", "Mac OS-X", "Unix"] 
MAJOR = 0 
MINOR = 1 
MICRO = 0 
ISRELEASED = False 
VERSION = '%d.%d.%d' % (MAJOR, MINOR, MICRO) 

INSTALL_REQUIRES=[] 
ZIP_SAFE=False 
TEST_SUITE='nose.collector' 
TESTS_REQUIRE=['nose'] 

DATA_FILES = [(NAME, ['LICENSE.txt','README.rst'])] 
PACKAGES=setuptools.find_packages() 
PACKAGES.remove('tools') 

PACKAGE_DATA={'': ['*.f95','*f90']}    
ext_files = get_package_data(NAME,['.f90', '.f95','.F90', '.F95']) 
ext_module_names = ['.'.join(osp.splitext(v)[0].split(osp.sep)) for v in ext_files] 
EXT_MODULES = [Extension(name=x,sources=[y]) for x, y in zip(ext_module_names, ext_files)]  


setup(
    name=NAME, 
    version=VERSION, 
    maintainer=MAINTAINER, 
    maintainer_email=MAINTAINER_EMAIL, 
    description=DESCRIPTION, 
    long_description=LONG_DESCRIPTION, 
    url=URL, 
    download_url=DOWNLOAD_URL, 
    license=LICENSE, 
    classifiers=CLASSIFIERS, 
    author=AUTHOR, 
    author_email=AUTHOR_EMAIL, 
    platforms=PLATFORMS, 
    packages=PACKAGES, 
    data_files=DATA_FILES, 
    install_requires=INSTALL_REQUIRES, 
    zip_safe=ZIP_SAFE, 
    test_suite=TEST_SUITE, 
    tests_require=TESTS_REQUIRE, 
    package_data=PACKAGE_DATA,  
    ext_modules=EXT_MODULES, 
    ) 

私が使用してコマンドラインで、インストールするには:

python setup.py install 
python setup.py clean --all 

唯一の問題は、マイナーな問題です。パッケージのサイトパッケージを見ると、eggフォルダC:\Python27\Lib\site-packages\pkg-0.1.0-py2.7-win32.egg\pkgの中にインストールされます。私がそこに見る他のほとんどのパッケージは、C:\Python27\Lib\site-packages\pkgフォルダがeggフォルダとは別にあります。誰もその分離を得る方法を知っていますか?テスト用として

、インストールした後、私は、コマンドラインで次のように入力します

nosetests package_name -v 

は、すべての変更後にパッケージをインストールする必要がないためpython setup.py developPython setup.py develop vs install)を調査してみます。

私は以下が有用であることが見出さコードにコメントしたように:

+0

非常に詳細な答えをありがとう。私はそれを適用し、それは私のユースケースのために働く。私はf2pyから離れ、代わりにCythonのものを書き直すことができました。私は[this](http://stackoverflow.com/a/13602504/841562)答えを使用してcythonセットアップのために。 – Lemming

2

ここに私が作ったプロジェクトのsetup.pyがあります。私は、setup.py/packagingを見つけ出して、固い答えが無くて欲求不満であることを発見しました。うまくいけば、これは少し助けてくれるでしょう。あなたが役に立つかもしれません

のポイントは以下のとおりです。

ファイルの多くを含むか、マニフェストの生成をいじりの雑用を削除
  • find_packages
  • package_dataこれにより、簡単に非を指定することができます。あなたはすでにそれを持っていない場合は、distribute_setup.pyのソースを見つける必要があります
  • install_requires/tests_require

を含めるPYファイル。

  • 拡張子のすべての単一のソースファイルへのパスを追加することが本当に必要ですか? (すなわち、volterra/integral.f90)volterra /の中に何かを探すパラメータ を与えることはできませんか? top_pathとpackage_dir のパラメータはこのトリックを行いませんでした。
  • 現在、 .pyファイルはビルドに含まれていません です。何故ですか?

うまくいけばfind_packages()はそれらの両方を解決します。私はパッケージングの経験はあまりありませんが、手作業での組み込みに戻らざるを得ませんでした。私はこの セットアップで私のテストを実行するにはどうすればよい

これは多分、あなたがテストをしているかどうかによって多くの答えが異なる質問でしょう。あなたは別にそれを聞くことができますか?

私は、テストディレクトリをトップレベルにすることが標準であるという印象を受けています。私。 volterra/volterraおよびvolterra/tests

  • な 環境で開発を行うための最良のワークフローは何ですか?私は毎回 のパッケージをインストールする必要はありません。 いくつかの拡張モジュールをコンパイルする必要がある場合、ソースディレクトリでどのように開発しますか?

これは別の質問の価値があるかもしれません。私はあなたが1回の変更ごとにあなたのパッケージをインストールする必要がある理由はわかりません。パッケージをアップロードする場合は、インストールをテストする以外はdevシステムにインストールせず、開発コピーから直接作業してください。私はコンパイルされた拡張機能で動作しないので、何かが欠けているかもしれません。ここで


は一例です。ここ

try: 
    from setuptools import setup, find_packages 
except ImportError: 
    from distribute_setup import use_setuptools 
    use_setuptools() 
    from setuptools import setup, find_packages 


setup(
    # ... other stuff 
    py_modules=['distribute_setup'], 
    packages=find_packages(), 
    package_data={'': ['*.png']}, # for me to include anything with png 
    install_requires=['numpy', 'treenode', 'investigators'], 
    tests_require=['mock', 'numpy', 'treenode', 'investigators'], 
) 
+0

あなたの答えをありがとう。私はrtrwalkerの解を探していました。私はあなたが示唆したように、サブテーマのいくつかを新しい個人的な質問として投稿することを検討します。 – Lemming