web-dev-qa-db-ja.com

Pythonプロジェクトでのリソースの管理

Pythonプロジェクトで、多くの非コードファイルを使用しています。現在、これらはすべて画像ですが、将来的には他の種類のファイルを使用する可能性があります。これらのファイルを保存して参照しますか?

メインディレクトリに「resources」というフォルダを作成することを検討しましたが、問題があります。一部の画像は、プロジェクトのサブパッケージ内から使用されています。これらの画像をそのように保存すると、結合につながり、これが欠点です。

また、現在のディレクトリが何であるかに依存しない、これらのファイルにアクセスする方法が必要です。

45
Ram Rachum

setuptoolsに付属する_pkg_resources_ライブラリを使用することもできます。

たとえば、使用するリソース編成スキームを示すために、簡単な小さなパッケージ_"proj"_を作成しました。

proj/setup.py 
 proj/proj/__ init __。py 
 proj/proj/code.py 
 proj/proj/resources/__ init __。py 
 proj/proj/resources/images/__ init __。py 
 proj/proj/resources/images/pic1.png 
 proj/proj/resources/images/pic2.png 

すべてのリソースを別のサブパッケージに保存する方法に注意してください。

_"code.py"_は、_pkg_resources_を使用してリソースオブジェクトを参照する方法を示しています。

_from pkg_resources import resource_string, resource_listdir

# Itemize data files under proj/resources/images:
print resource_listdir('proj.resources.images', '')
# Get the data file bytes:
print resource_string('proj.resources.images', 'pic2.png').encode('base64')
_

実行すると、次のようになります。

['__init__.py'、 '__init __。pyc'、 'pic1.png'、 'pic2.png'] 
 iVBORw0KGgoAAAANSUhE ... 

リソースをファイルオブジェクトとして扱う必要がある場合は、resource_stream()を使用します。

リソースにアクセスするコードは、プロジェクトのサブパッケージ構造内のどこにあってもかまいません。この場合は、イメージを含むサブパッケージをフルネーム__proj.resources.images_で参照するだけです。

これが_"setup.py"_です:

_#!/usr/bin/env python

from setuptools import setup, find_packages

setup(name='proj',
      packages=find_packages(),
      package_data={'': ['*.png']})
_

警告:「ローカル」にテストする、つまり最初にパッケージをインストールしない場合は、_setup.py_があるディレクトリからテストスクリプトを呼び出す必要があります。 _code.py_と同じディレクトリにいる場合、Pythonはprojパッケージを認識しません。したがって、_proj.resources_のようなものは解決されません。

52
Pavel Repin

それを必要とする各サブパッケージに常に個別の「resources」フォルダーを配置し、os.path関数を使用して、サブパッケージの__file__値からこれらにアクセスできます。意味を説明するために、次の__init__.pyファイルを3つの場所に作成しました。

 c:\ temp\topp(トップレベルパッケージ)
 c:\ temp\topp\sub1(サブパッケージ1)
 c:\ temp\topp\sub2(サブパッケージ2 )

これが__init__.pyファイルです。

import os.path
resource_path = os.path.join(os.path.split(__file__)[0], "resources")
print resource_path

C:\ temp\workで、次のようにアプリtopapp.pyを作成します。

import topp
import topp.sub1
import topp.sub2

これは、toppパッケージとサブパッケージを使用するアプリケーションを表しています。次に、それを実行します。

 C:\ temp\work> topapp 
 Traceback(最後の最新の呼び出し):
ファイル「C:\ temp\work\topapp.py」、1行目の
 import topp 
 ImportError:toppという名前のモジュールはありません

それは予想通りです。 PYTHONPATHを設定して、パス上にパッケージがあることをシミュレートします。

 C:\ temp\work> set PYTHONPATH = c:\ temp 
 
 C:\ temp\work> topapp 
 c:\ temp\topp\resources 
 c:\ temp\topp\sub1\resources 
 c:\ temp\topp\sub2\resources 

ご覧のとおり、リソースパスはパス上の実際の(サブ)パッケージの場所に正しく解決されています。

更新:ここ は、関連するpy2exeドキュメントです。

5
Vinay Sajip

@ pycon2009、distutilsとsetuptoolsに関するプレゼンテーションがありました。あなたはここですべてのビデオを見つけることができます

Python-パート1 での卵とBuildoutのデプロイ

Python-パート2 での卵とBuildoutのデプロイ

Python-パート3 での卵とBuildoutのデプロイ

これらのビデオでは、パッケージに静的リソースを含める方法について説明しています。パート2だと思います。

Setuptoolsを使用すると、依存関係を定義できます。これにより、3番目のパッケージのリソースを使用する2つのパッケージを作成できます。

Setuptoolsはまた、これらのリソースにアクセスする標準的な方法を提供し、パッケージ内で相対パスを使用できるようにします。これにより、パッケージがインストールされている場所を気にする必要がなくなります。

1
Taras Mankovski