2016-11-17 31 views
0

メタデータを更新する必要があるフォルダとサブフォルダに約300のdocxファイルがあります。私はメタデータを含む別々の300行以上のcsvファイルを持っています:各行はファイル名、キーワード、行のタイトルを含んでいます。python-docxを使用して多数のファイルのdocxメタデータを更新します

私は、csvからコンテンツをプルするdocxファイルをループし、そのメタデータをdocxファイルに挿入したいと考えています。 Docxファイルは、ルートフォルダから2つのサブフォルダに格納されます。

これまでのところ、私は次のことを説明しました。私が苦労しているのは、csvファイルをループする方法と、各ファイルにメタデータを順番に適用する方法です。私はこのアプローチに比較的容易な方法があると確信しています。ループを設定し、csvのコンテンツを取得するのは、私が紛失した場所です。私はノブなので、私が行くように自分のやり方を感じる。

ヒントありがとうございます。

#running in python 3.5.2 32bit 
import csv 
from docx import Document 
import os 
import sys 

csv_path = ("datasheet_metadata_uplift.csv") 

def update_docx_metadata(document, keywords, title): 
    """ 
    Update the *keywords*, and *title* metadata 
    properties in *document*. 
    """ 
    core_properties = document.core_properties 
    core_properties.keywords = keywords 
    core_properties.title = title 

def read_csv_lines(filename, keywords, title): 
    """ 
    Reads the csv lines, returns *filename*, *keywords*, *title* 
    """ 
    with open(csv_path, 'r') as f: 
     csv_file = csv.reader(f) 
     for row in csv_file: 
      filename = row[0] 
      keywords = row[1] 
      title = row[2] 

def open_docx(filename): 
    """ 
    Search for docx file and open it 
    """ 
    for root, dirs, files in os.walk("."): 
     if filename in files: 
      doc_path = os.path.join(path, filename) 

csv_lines = read_csv_lines(filename, keywords, title) 
for filename, keywords, title in csv_lines: 
    document = Document(doc_path) 
    update_doc_metadata(filename, keywords, title) 
    document.save(doc_path) 

答えて

0

次のステップでは、コードをコヒーレントな機能にリファクタリングすることをお勧めします。これにより、インテントとフローが不明瞭にならないように、それぞれが単一の関数呼び出しで必要なアクションを実行することができます。

あなたはこのような何かを開始する可能性があります:それはそれは一つだけのすべてを行いつまり、コヒーレントだ

  • def update_doc_metadata(document, author, keywords, title, subject): 
        """ 
        Update the *author*, *keywords*, *title*, and *subject* metadata 
        properties in *document*. 
        """ 
        core_properties = document.core_properties 
        core_properties.author = author 
        core_properties.keywords = keywords 
        core_properties.title = title 
        core_properties.subject = subject 
    

    お知らせいくつかのこと。これはより再利用可能です。

  • パラメータとして入力されていないものに依存しません。これにより、(必要ならば)簡単にテストすることができ、必要なすべてのコンテキストがその10行にあるため、理解しやすくなります。
  • それは、それが何を明白に述べているdocstringを持っています。これは、読者(おそらく、数週間または数か月後)が意図を理解するのに役立つだけでなく、自分が行っていることを説明するために役立つからです。あなたが説明するのが難しくて長くて済むので、誤ってファクタリングされた機能を検出することができます。 (パラメータの周りのアスタリスクは、それらが特定の文書パッケージ内のイタリック体で表示します。)

あなたはこのように続行すると、位置及び機能にコヒーレントビットを「抽出」、メインコードのコアロジックは非常になります明らかに。

私は、全体的な構造はこのようなものだと思う:

csv_lines = read_csv_lines(csv_path) 
for filename, keywords, title in csv_lines: 
    doc_path, document = open_docx(filename) 
    update_doc_metadata(document, author, keywords, title, subject) 
    document.save(doc_path) 
+0

こんにちはスカニー - ありがとう!非常に有用な答え、私はあなたが示唆するように機能を使用するためにリファクタリングしてきましたが、何かが正しくないです。私は、 'NameError:name 'ファイル名の'定義されていません 'というコードの最後の部分に関連するエラーを取得します。元の投稿を新しいコードで更新しました。 どのような考えですか? – Aidan

+0

@Aidan私はあなたがPythonで関数のパラメータの役割を混乱させるかもしれないと思います。彼らは値を*関数に入れるが、一般的には* out *ではない。そのためにはreturn文が必要です。だから、read_csv_linesはパラメータとしてcsv_pathを取って、(ファイル名、キーワード、タイトル)シーケンス(たぶんタプル)のシーケンス(おそらくリスト)を返してください。 read_csv_linesの返り値は 'return [row for row in csv_file]'だと思います。 Pythonのチュートリアルのリソースのいくつかを見つけることができます。私は[この1つ](https://pymotw.com/3/)が好きで、Pythonの公式チュートリアルもかなり良いです:) – scanny

+0

あなたの助けを借りてくれてありがとう、私は今日これを見ていたことを実感しました。 – Aidan

0

ので、私はそれが非常に簡単になってしまった、これを考え出しました。私はまた、csvに完全なファイルパスを入れることで自分自身をより簡単にしました。励ましのためのスカニーのおかげで。次の停止、ドキュメントとチュートリアルのページ:

#runs in python 3.5.2 32-bit 
#docx requires 32 bit operation 
import csv 
from docx import Document 
import os 
import sys 

#path to the csv file - csv file must contain rows as follows: 
#full filepath, title, subject 
#ensure there are no commas, other than the csv delimiters 

csv_path = "datasheet_metadata_uplift.csv" 

#set up the lists that will be used to hold csv values 
filename = [] 
title = [] 
keywords = [] 

#sets up the csv file, and parses the "columns" to one of three lists: filename, title, keywords 
f = open(csv_path) 
csv_file = csv.reader(f) 

#chops up csv into [] lists 
for row in csv_file: 
    filename.append(row[0]) 
    title.append(row[1]) 
    keywords.append(row[2]) 

#get the number of lines in the csv, and thus the number of files that need updating 
file = open(csv_path) 
num_lines = len(file.readlines()) 

#do the updates on every filename in the list 
i = 0 
while i < num_lines: 
    if i < num_lines: 
     #update the docx files, one for each csv file entry 
     document = Document(filename[i]) 
     core_properties = document.core_properties 
     core_properties.keywords = (keywords[i]) 
     core_properties.title = (title[i]) 
     core_properties.subject = ("YOUR_SUBJECT_HERE") 
     core_properties.comments = (" ") 
     core_properties.company = ("YOUR_COMPANY_HERE") 
     document.save(filename[i]) 
     i+=1 

print ("finished!") 
関連する問題