2009-04-22 11 views
65

私は./data/サブディレクトリにデータファイルを開く必要のあるモジュールを含むpythonパッケージを作成しています。今、私はクラスと関数にハードコードされたファイルへのパスを持っています。私は、ユーザーのシステムにインストールされている場所に関係なく、サブディレクトリにアクセスできるより堅牢なコードを作成したいと考えています。Python Access Data in Packageサブディレクトリ

私はさまざまな方法を試しましたが、これまでのところ私は運がありませんでした。ほとんどの "カレントディレクトリ"コマンドは、モジュールのディレクトリではなく、システムのPythonインタプリタのディレクトリを返すようです。

これは、普通の問題ではないようです。しかし、私はそれを理解するように見えることはできません。問題の一部は、私のデータファイルが.pyのファイルではないため、インポート機能などを使用できません。

提案がありますか?私はdata.txt

module*.pyからの感謝にアクセスしようとしています

/ 
__init__.py 
module1.py 
module2.py 
data/ 
    data.txt 

は、今のところ私のパッケージディレクトリは次のようになります!

答えて

24

ですべての私のファイルを開くにファイル・アンダースコア・アンダースコア(__file__)このように、パッケージへのパスを取得します

import os 
this_dir, this_filename = os.path.split(__file__) 
DATA_PATH = os.path.join(this_dir, "data", "data.txt") 
print open(DATA_PATH).read() 
+24

ファイルがディストリビューション(IE。egg)にある場合、これは機能しません。 pkg_resourcesを使用してデータファイルを取得します。 – Chris

+0

実際これは壊れています。 – Federico

6

私は答えを捜したと思う。

私は含んで私の他のモジュールにインポートモジュールdata_path.py、作る:

data_path = os.path.join(os.path.dirname(__file__),'data') 

そして、私はあなたがアンダースコア-underscore-を使用することができます

open(os.path.join(data_path,'filename'), <param>) 
+0

これは、リソースがアーカイブ配布(zipされた卵など)にあるときには機能しません。そのようなものを好む: 'pkg_resources.resource_string(「pkg_name」、「データ/ file.txtを」)' – ankostis

+0

@ankostisのsetuptoolsのは、それはあなたがどこかに '__file__'を使用したことを検知した場合にアーカイブを展開してくれています。私の場合は、実際にはストリームではなくストリームを必要とするライブラリを使用します。もちろん、ファイルを一時的にディスクに書き込むことはできますが、私はsetuptoolsの機能を使用するだけです。 – letmaik

95

これを行う標準的な方法は、setuptoolsパッケージとpkg_resourcesです。

あなたは次の階層に応じて、あなたのパッケージをレイアウトし、このリンクに従って、それあなたのデータリソースを指すように、パッケージのセットアップファイルを設定することができます。

http://docs.python.org/distutils/setupscript.html#installing-package-data

あなたは再度見つけることができますし、このリンクに従って、pkg_resourcesを使用してそれらのファイルを使用します。

http://peak.telecommunity.com/DevCenter/PkgResources#basic-resource-access

import pkg_resources 

DATA_PATH = pkg_resources.resource_filename('<package name>', 'data/') 
DB_FILE = pkg_resources.resource_filename('<package name>', 'data/sqlite.db') 
+0

私はこれが好ましい方法だと思っていますが、その理由は完全にはわかりませんが、パッケージ/モジュールを '__file__'で参照すると警告が表示されます。 – lukecampbell

+1

* pkg_resources *は* setuptools *にランタイム依存関係を作成しませんか?例えば、私はDebianパッケージを再配布するのですが、どうして 'python-setuptools'に依存するのでしょうか?これまでのところ、 '__file__'はうまく動作します。 – mlt

+3

なぜこれが良いのですか?ResourceManagerクラスは、パッケージリソースへの一様なアクセスを提供します。それらのリソースがファイルやディレクトリとして存在するか、何らかのアーカイブに圧縮されています。 – vrdhn

11

へ今日のソリューションを提供してください。間違いなくこのAPIを使用して、すべてのホイールを再開発しないでください。

実際のファイルシステムファイル名が必要です。圧縮された卵は、キャッシュディレクトリに展開されます。

from pkg_resources import resource_filename, Requirement 

path_to_vik_logo = resource_filename(Requirement.parse("enb.portals"), "enb/portals/reports/VIK_logo.png") 

指定されたリソースの読み取り可能なファイルのようなオブジェクトを返します。実際のファイル、StringIO、または同様のオブジェクトである可能性があります。ストリームは「バイナリモード」にあります。つまり、リソース内のどのバイトでもそのまま読み込まれます。

from pkg_resources import resource_stream, Requirement 

vik_logo_as_stream = resource_stream(Requirement.parse("enb.portals"), "enb/portals/reports/VIK_logo.png") 

パッケージディスカバリーおよびリソースアクセスpkg_resourcesを使用して

3

あなたはあなたの全体のモジュールの名前を必要とする、あなたは、ディレクトリツリーが表示されません与えられていますその詳細、私のためにこれは働いた:

import pkg_resources 
print( 
    pkg_resources.resource_filename(__name__, 'data/data.txt') 
) 

Notibly setuptoolsのは秀あなたがガナどんなかなりのdata/接頭辞を含まないように持っている、パックされたデータファイルと名前が一致に基づいてファイルを解決するためには表示されません。別のディレクトリ区切り文字が必要な場合はos.path.join('data', 'data.txt)を使うことができます。一般に、ハードコードされたUNIXスタイルのディレクトリ区切り文字との互換性の問題はありません。