Python 3.2 で多数のファイル (たとえば 30 ~ 40) を読み取る場合、ファイル参照をリストに保持したい場合
(すべてのファイルは共通のフォルダーにあります)
とにかく、file.open()関数を介してすべてのファイルを個別に開くことなく、リスト内のそれぞれのファイルハンドルにすべてのファイルを開く方法はありますか?
Python 3.2 で多数のファイル (たとえば 30 ~ 40) を読み取る場合、ファイル参照をリストに保持したい場合
(すべてのファイルは共通のフォルダーにあります)
とにかく、file.open()関数を介してすべてのファイルを個別に開くことなく、リスト内のそれぞれのファイルハンドルにすべてのファイルを開く方法はありますか?
これは簡単です。ファイル パスのリストに基づいてリスト内包表記を使用するだけです。または、一度に 1 つずつアクセスする必要がある場合は、ジェネレータ式を使用して、40 個のファイルすべてを一度に開いたままにしないようにします。
list_of_filenames = ['/foo/bar', '/baz', '/tmp/foo']
open_files = [open(f) for f in list_of_filenames]
特定のディレクトリ内のすべてのファイルのハンドルが必要な場合は、次のos.listdir
関数を使用します。
import os
open_files = [open(f) for f in os.listdir(some_path)]
ここではシンプルでフラットなディレクトリを想定していますが、指定されたディレクトリ内のすべてのファイル オブジェクトへのパスのリストが返されることに注意してください。os.listdir
したがって、開いているディレクトリ内にディレクトリがある場合は、次を使用して結果をフィルタリングする必要がありますos.path.isfile
。
import os
open_files = [open(f) for f in os.listdir(some_path) if os.path.isfile(f)]
また、os.listdir
パス全体ではなく生のファイル名のみを返すため、現在の作業ディレクトリが でないsome_path
場合は、 を使用して絶対パスを作成する必要がありますos.path.join
。
import os
open_files = [open(os.path.join(some_path, f)) for f in os.listdir(some_path)
if os.path.isfile(f)]
ジェネレータ式の場合:
import os
all_files = (open(f) for f in os.listdir(some_path)) # note () instead of []
for f in all_files:
pass # do something with the open file here.
いずれの場合も、作業が終わったら必ずファイルを閉じてください。Python 3.3 以降にアップグレードできる場合は、ExitStack
もう 1 つの利便性のために を使用することをお勧めします。
os
ライブラリ (特にlistdir
) は、必要な基本的なツールを提供する必要があります。
import os
print("\n".join(os.listdir())) # returns all of the files (& directories) in the current directory
明らかに、それらを呼び出したいと思うでしょうopen
が、これにより、ファイルが反復可能な形式で提供されます(これが、直面している問題の核心だと思います)。この時点で、for
ループを実行してすべて (または一部) を開くことができます。
os.listdir
簡単な警告: Jon Clements は、Henry Keiter の回答のコメントで、ファイルと共に表示されるディレクトリに注意する必要があると指摘しました。
さらに、適切な種類のファイルのみを開こうとすることを確認するために、いくつかのフィルター ステートメントを記述する良い機会です。今はディレクトリに .txt ファイルしかないだろうと考えているかもしれませんが、いつの日か、オペレーティング システム (またはユーザー) がそこに別のファイルを配置するという巧妙なアイデアを思い付き、コードに問題が生じる可能性があります。
幸いなことに、クイック フィルターでそれを行うことができ、いくつかの方法でそれを行うことができます (ここでは正規表現フィルターを示します)。
import os,re
scripts=re.compile(".*\.py$")
files=[open(x,'r') for x in os.listdir() if os.path.isfile(x) and scripts.match(x)]
files=map(lambda x:x.read(),files)
print("\n".join(files))
ファイルにアクセスする権限があるかどうかなどをチェックしていないことに注意してください。したがって、ディレクトリ内のファイルを表示する権限はあるが、読み取る権限がない場合は、例外が発生します。