上記の回答を組み合わせて明確にする試みとして、私自身の回答を書くことにしました(これは私の問題を解決するのに大いに役立ちました)。
この問題には2つのアプローチがあると思います。
状況 1: ファイルに含まれるメタデータ (関心のあるメタデータ) がわかっている場合。
この場合、関心のあるメタデータを含む文字列のリストがあるとします。ここでは、これらのタグが正しいと仮定します (つまり、.txt ファイルのピクセル数には関心がありません)。
metadata = ['Name', 'Size', 'Item type', 'Date modified', 'Date created']
ここで、Greedo と Roger Upole によって提供されたコードを使用して、ファイルのフル パスと名前を個別に受け取り、対象のメタデータを含む辞書を返す関数を作成しました。
def get_file_metadata(path, filename, metadata):
# Path shouldn't end with backslash, i.e. "E:\Images\Paris"
# filename must include extension, i.e. "PID manual.pdf"
# Returns dictionary containing all file metadata.
sh = win32com.client.gencache.EnsureDispatch('Shell.Application', 0)
ns = sh.NameSpace(path)
# Enumeration is necessary because ns.GetDetailsOf only accepts an integer as 2nd argument
file_metadata = dict()
item = ns.ParseName(str(filename))
for ind, attribute in enumerate(metadata):
attr_value = ns.GetDetailsOf(item, ind)
if attr_value:
file_metadata[attribute] = attr_value
return file_metadata
# *Note: you must know the total path to the file.*
# Example usage:
if __name__ == '__main__':
folder = 'E:\Docs\BMW'
filename = 'BMW series 1 owners manual.pdf'
metadata = ['Name', 'Size', 'Item type', 'Date modified', 'Date created']
print(get_file_metadata(folder, filename, metadata))
結果:
{'Name': 'BMW series 1 owners manual.pdf', 'Size': '11.4 MB', 'Item type': 'Foxit Reader PDF Document', 'Date modified': '8/30/2020 11:10 PM', 'Date created': '8/30/2020 11:10 PM'}
ファイルを作成したばかりで、Foxit PDFリーダーをメインのPDFリーダーとして使用しているため、これは正しいです。したがって、この関数はディクショナリを返します。キーはメタデータ タグであり、値は指定されたファイルのそれらのタグの値です。
状況 2: ファイルに含まれるメタデータがわからない
これは、特に最適性の点で、やや厳しい状況です。Roger Upole によって提案されたコードを分析したところ、基本的に、彼はNone
ファイルのメタデータを読み取ろうとし、その結果、考えられるすべてのメタデータ タグのリストを取得しました。したがって、このリストをハードコピーしてからすべてのタグを読み取ろうとする方が簡単かもしれないと考えました。そうすれば、完了したら、ファイルが実際に持っているすべてのタグを含む辞書ができます。
私が考えているすべてのメタデータタグをコピーして、ファイルからすべてのタグを取得しようとするだけです。基本的に、Python リストのこの宣言をコピーして、上記のコードを使用します (メタデータをこの新しいリストに置き換えます)。
metadata = ['Name', 'Size', 'Item type', 'Date modified', 'Date created', 'Date accessed', 'Attributes', 'Offline status', 'Availability', 'Perceived type', 'Owner', 'Kind', 'Date taken', 'Contributing artists', 'Album', 'Year', 'Genre', 'Conductors', 'Tags', 'Rating', 'Authors', 'Title', 'Subject', 'Categories', 'Comments', 'Copyright', '#', 'Length', 'Bit rate', 'Protected', 'Camera model', 'Dimensions', 'Camera maker', 'Company', 'File description', 'Masters keywords', 'Masters keywords']
これは素晴らしい解決策ではないと思いますが、一方で、このリストをグローバル変数として保持し、すべての関数呼び出しに渡す必要なく使用できます。完全を期すために、この新しいメタデータ リストを使用した前の関数の出力を次に示します。
{'Name': 'BMW series 1 owners manual.pdf', 'Size': '11.4 MB', 'Item type': 'Foxit Reader PDF Document', 'Date modified': '8/30/2020 11:10 PM', 'Date created': '8/30/2020 11:10 PM', 'Date accessed': '8/30/2020 11:10 PM', 'Attributes': 'A', 'Perceived type': 'Unspecified', 'Owner': 'KEMALS-ASPIRE-E\\kemal', 'Kind': 'Document', 'Rating': 'Unrated'}
ご覧のとおり、返されたディクショナリには、ファイルに含まれるすべてのメタデータが含まれています。これが機能する理由は、if ステートメントのためです。
if attribute_value:
つまり、属性が と等しいときはいつでもNone
、返される辞書に追加されません。
多くのファイルを処理する場合は、リストを毎回関数に渡すのではなく、グローバル/静的変数として宣言する方がよいことを強調しておきます。