web-dev-qa-db-ja.com

Pythonスクリプトと同じディレクトリにあるファイルを確実に開く方法

次のようなコマンドを使用して、現在実行中のPythonスクリプトと同じディレクトリにあるファイルを開きました。

open("Some file.txt", "r")

ただし、Windowsでスクリプトをダブルクリックして実行すると、スクリプトが間違ったディレクトリからファイルを開こうとすることがわかりました。

それ以来、私は次の形式のコマンドを使用しました

open(os.path.join(sys.path[0], "Some file.txt"), "r")

ファイルを開きたいときはいつでも。これは私の特定の用途では機能しますが、sys.path[0]が他のユースケースで失敗するかどうかはわかりません。

私の質問は次のとおりです。現在実行中のPythonスクリプトと同じディレクトリにあるファイルを開くための最良かつ最も信頼できる方法は何ですか?

これまでに私が理解できたことは次のとおりです。

  • os.getcwd()およびos.path.abspath('')は、スクリプトディレクトリではなく、「現在の作業ディレクトリ」を返します。

  • os.path.dirname(sys.argv[0])およびos.path.dirname(__file__)は、スクリプトを呼び出すために使用されるパスを返します。相対パスまたは空の場合もあります(スクリプトがcwdにある場合)。また、スクリプトがIDLEまたはPythonWinで実行される場合、__file__は存在しません。

  • sys.path[0]およびos.path.abspath(os.path.dirname(sys.argv[0]))は、スクリプトディレクトリを返すようです。これら2つの間に違いがあるかどうかはわかりません。

編集:

私がやりたいことは、「含まれているモジュールと同じディレクトリにあるファイルを開く」と説明する方が良いことに気づいたところです。つまり、別のディレクトリにあるモジュールをインポートし、そのモジュールがファイルを開く場合、モジュールのディレクトリでファイルを検索するようにしたいのです。私が見つけた何もそれをすることができるとは思わない...

136
dln385

私はいつも使用します:

__location__ = os.path.realpath(
    os.path.join(os.getcwd(), os.path.dirname(__file__)))

join()呼び出しは現在の作業ディレクトリの先頭に追加されますが、ドキュメントでは、一部のパスが絶対パスである場合、そのパスの他のすべてのパスは削除されると記載されています。したがって、getcwd()が絶対パスを返すと、dirname(__file__)は削除されます。

また、realpath呼び出しは、シンボリックリンクが見つかった場合に解決します。これにより、Linuxシステムでsetuptoolsを使用してデプロイする際のトラブルを回避できます(スクリプトは/usr/bin/-少なくともDebianではシンボリックリンクされています)。

次を使用して、同じフォルダ内のファイルを開くことができます。

f = open(os.path.join(__location__, 'bundled-resource.jpg'));
# ...

これを使用して、WindowsとLinuxの両方でいくつかのDjangoアプリケーションにリソースをバンドルします。

164
André Caron

Pythonドキュメントから引用するには:

プログラムの起動時に初期化されると、このリストの最初の項目path [0]は、Pythonインタープリターの呼び出しに使用されたスクリプトを含むディレクトリです。スクリプトディレクトリが利用できない場合(たとえば、インタープリターが対話的に呼び出される場合、またはスクリプトが標準入力から読み取られる場合)、path [0]は空の文字列であり、Pythonに現在のモジュールを検索します最初にディレクトリ。 PYTHONPATHの結果としてエントリが挿入される前に、スクリプトディレクトリが挿入されることに注意してください。

sys.path [0]は探しているものです。

33
RED MONKEY

OKここで私がやること

sys.argvは、常にターミナルに入力するか、python.exeまたはpythonw.exeで実行するときにファイルパスとして使用するものです。

たとえば、ファイルtext.pyをいくつかの方法で実行できます。それぞれが異なる答えを提供し、常にpythonが入力されたパスを提供します。

    C:\Documents and Settings\Admin>python test.py
    sys.argv[0]: test.py
    C:\Documents and Settings\Admin>python "C:\Documents and Settings\Admin\test.py"
    sys.argv[0]: C:\Documents and Settings\Admin\test.py

わかりましたので、あなたはファイル名を取得できることを知ってください、大いに今、あなたが知っているアプリケーションディレクトリを取得するには、os.path、特にabspathとdirnameを使用してください

    import sys, os
    print os.path.dirname(os.path.abspath(sys.argv[0]))

これはこれを出力します:

   C:\Documents and Settings\Admin\

python test.pyまたはpython "C:\ Documents and Settings\Admin\test.py"と入力しても、常にこれが出力されます。

__ file__の使用に関する問題これら2つのファイルtest.pyを検討してください

import sys
import os

def paths():
        print "__file__: %s" % __file__
        print "sys.argv: %s" % sys.argv[0]

        a_f = os.path.abspath(__file__)
        a_s = os.path.abspath(sys.argv[0])

        print "abs __file__: %s" % a_f
        print "abs sys.argv: %s" % a_s

if __== "__main__":
    paths()

import_test.py

import test
import sys

test.paths()

print "--------"
print __file__
print sys.argv[0]

「python test.py」の出力

C:\Documents and Settings\Admin>python test.py
__file__: test.py
sys.argv: test.py
abs __file__: C:\Documents and Settings\Admin\test.py
abs sys.argv: C:\Documents and Settings\Admin\test.py

「python test_import.py」の出力

C:\Documents and Settings\Admin>python test_import.py
__file__: C:\Documents and Settings\Admin\test.pyc
sys.argv: test_import.py
abs __file__: C:\Documents and Settings\Admin\test.pyc
abs sys.argv: C:\Documents and Settings\Admin\test_import.py
--------
test_import.py
test_import.py

fileを見るとわかるように、常にpythonファイルが実行されます。sys.argv[0]は、常にインタープリターから実行したファイルを提供します。ニーズに応じて、ニーズに最適なものを選択する必要があります。

18
Zimm3r

私はこのようにします:

from os.path import abspath, exists

f_path = abspath("fooabar.txt")

if exists(f_path):
    with open(f_path) as f:
        print f.read()

上記のコードは abspath を使用してファイルへの絶対パスを構築し、normpath(join(os.getcwd(), path)) [pydocsから]を使用するのと同等です。次に、そのファイルが実際に exists であるかどうかを確認し、コンテキストマネージャーを使用してそれを開きます。そのため、ファイルハンドルでcloseを呼び出す必要はありません。私見、この方法でそれをすることは長期的にあなたの多くの苦痛を救います。

0
dcolish