web-dev-qa-db-ja.com

Pythonでコードリポジトリを操作するときにリソースの相対パスを参照する方法

WindowsとLinuxの両方に展開されるコードリポジトリを使用しています(時には異なるディレクトリにあります)。プロジェクト内のモジュールの1つは、プロジェクト内の非Pythonリソース(CSVファイルなど)の1つをどのように参照する必要がありますか?

次のようなことをする場合:

thefile=open('test.csv')

または:

thefile=open('../somedirectory/test.csv')

特定のディレクトリ、またはディレクトリのサブセットからスクリプトが実行される場合にのみ機能します。

私がやりたいことは次のようなものです:

path=getBasePathOfProject()+'/somedirectory/test.csv'
thefile=open(path)

これは正しい方法ですか?出来ますか?

165
olamundo

現在のファイルパスに関連するファイル名を使用してみてください。 「./my_file」の例:

fn = os.path.join(os.path.dirname(__file__), 'my_file')

Python 3.4+では、 pathlib も使用できます。

fn = pathlib.Path(__file__).parent / 'my_file'
224
c089

セットアップツールを使用するか、配布(setup.pyインストール)する場合、これらのパッケージ化されたリソースにアクセスする「正しい」方法はpackage_resourcesを使用しているようです。

あなたの場合、例は

import pkg_resources
my_data = pkg_resources.resource_string(__name__, "foo.dat")

もちろん、リソースを読み取り、読み取られたバイナリデータはmy_dataの値になります

ファイル名だけが必要な場合は、使用することもできます

resource_filename(package_or_requirement, resource_name)

例:

resource_filename("MyPackage","foo.dat")

利点は、Eggのようなアーカイブ配布であっても機能することが保証されていることです。

http://packages.python.org/distribute/pkg_resources.html#resourcemanager-api を参照してください

35
Sharoon Thomas

私はよくこれに似たものを使用します:

import os
DATA_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), 'datadir'))

# if you have more paths to set, you might want to shorten this as
here = lambda x: os.path.abspath(os.path.join(os.path.dirname(__file__), x))
DATA_DIR = here('datadir') 

pathjoin = os.path.join
# ...
# later in script
for fn in os.listdir(DATA_DIR):
    f = open(pathjoin(DATA_DIR, fn))
    # ...

変数

__file__

そのコードを記述するスクリプトのファイル名を保持するため、スクリプトに相対するパスを作成できますが、それでも絶対パスで作成できます。それはいくつかの理由で非常にうまく機能します:

  • パスは絶対ですが、それでも相対的です
  • プロジェクトは引き続き相対コンテナにデプロイできます

ただし、プラットフォームの互換性に注意する必要があります-Windowsのos.pathsepはUNIXとは異なります。

12
user137673

Pythonでは、パスはcurrent working directoryに関連しています。これはほとんどの場合、プログラムを実行するディレクトリです。 現在の作業ディレクトリはモジュールファイルのディレクトリと同じではない可能性が高いため、現在のモジュールファイルに対する相対パスを使用することは常に悪いことです選択。

絶対パスを使用することが最善の解決策です。

import os
package_dir = os.path.dirname(os.path.abspath(__file__))
thefile = os.path.join(package_dir,'test.cvs')
12
skyfree
import os
cwd = os.getcwd()
path = os.path.join(cwd, "my_file")
f = open(path)

また、os.path.abspath(os.getcwd())を使用してcwdを正規化しようとします。詳細 こちら

6
gavoja

__file__変数でビルドを使用できます。現在のファイルのパスが含まれています。プロジェクトのルートにあるモジュールにgetBaseOfProjectを実装します。そこで、__file__のパス部分を取得し、それを返します。このメソッドは、プロジェクトのあらゆる場所で使用できます。

2
Achim

ここで少し困惑しました。いくつかのリソースファイルをホイールファイルにパッケージ化し、それらにアクセスしたい。マニフェストファイルを使用してパッケージ化しましたが、サブディレクトリでない限り、pip installはパッケージをインストールしませんでした。これらのシーンショットが役立つことを願っています

├── cnn_client
│   ├── image_preprocessor.py
│   ├── __init__.py
│   ├── resources
│   │   ├── mscoco_complete_label_map.pbtxt
│   │   ├── retinanet_complete_label_map.pbtxt
│   │   └── retinanet_label_map.py
│   ├── tf_client.py

MANIFEST.in

recursive-include cnn_client/resources *

標準のsetup.pyを使用してウィールを作成しました。 pipはwheelファイルをインストールしました。インストール後、リソースがインストールされているかどうかを確認しました。彼らです

ls /usr/local/lib/python2.7/dist-packages/cnn_client/resources

mscoco_complete_label_map.pbtxt
retinanet_complete_label_map.pbtxt 
 retinanet_label_map.py  

Tfclient.pyでこれらのファイルにアクセスします。 from

templates_dir = os.path.join(os.path.dirname(__file__), 'resources')
 file_path = os.path.join(templates_dir, \
            'mscoco_complete_label_map.pbtxt')
        s = open(file_path, 'r').read()

そしてそれは動作します。

0
Alex Punnen