convert.py - ファイル変換ユーティリティ

プログラムの動作

convert.py は、様々なファイル形式を別の形式へ自動的に変換するための汎用ユーティリティです。このプログラムは、指定されたディレクトリツリー内、または単一のファイルを走査し、設定された変換ルールに基づいてファイルを処理します。主に、オフィスドキュメント(Word, Excel, PowerPoint)、Markdown、Jupyter Notebook、画像ファイルなどをPDF、Markdown、HTML、または画像コレクション(PNGなど)に変換する用途を想定しています。

主な機能は以下の通りです。

  • 多様なファイル形式のサポート: 多くの一般的なドキュメント形式や画像形式に対応しています。

  • ディレクトリの再帰的走査: 指定されたルートディレクトリからファイルを再帰的に検索し、変換可能なファイルを処理します。

  • 単一ファイル変換: 特定のファイルのみを変換することも可能です。

  • 条件付き変換: ファイルのタイムスタンプを比較し、入力ファイルが出力ファイルより新しい場合のみ変換を実行する「更新」モードや、常に変換を実行する「上書き」モードをサポートします。

  • ファイルフィルタリング: 特定のファイル名パターンに一致するファイルのみを対象とすることができます。

  • 拡張可能な変換システム: 外部のPythonライブラリをプラグインとして動的に読み込み、新しい変換パスを容易に追加できます。

  • Pandoc連携: MarkdownからWord、PowerPoint、HTMLへの変換において、Pandocの詳細なオプション(テンプレート、CSS、目次など)を利用できます。

このツールは、多数のファイルを一括して管理・変換する必要がある場合に特に役立ちます。

原理

convert.py は、柔軟な変換システムを構築するためにいくつかの主要なコンポーネントとアルゴリズムを採用しています。

  1. ConverterSpec クラス:

    • 各変換パス(例: .docx から .pdf)の仕様を定義するデータクラスです。

    • input_ext(入力拡張子)、output_ext(出力拡張子)、converter(実際の変換処理を行う関数)、description(説明)、output_mode(出力が単一ファイルかディレクトリか)、options(変換関数に渡す追加オプション)などの属性を持ちます。

    • 拡張子は .docx のように正規化され、大文字小文字を区別しません。

  2. ConverterRegistry クラス:

    • 利用可能なすべての ConverterSpec オブジェクトを管理するレジストリです。

    • (input_ext, output_ext) のタプルをキーとして ConverterSpec を登録、取得します。

    • 外部ライブラリのインポート時に発生したエラーを記録し、利用できない変換パスをユーザーに通知する機能も持ちます。

  3. 拡張子の正規化 (normalize_ext):

    • すべての拡張子は小文字に変換され、先頭にドットがない場合は付加されます(例: "pdf"".pdf" に)。これにより、拡張子の一貫した処理を保証します。

  4. 出力パスの構築 (build_output_path):

    • 入力ファイルパスと ConverterSpecoutput_mode に基づいて、出力ファイルのパスを生成します。

    • OUTPUT_MODE_FILE の場合、入力ファイルの基本名に出力拡張子を付けます(例: doc.docx -> doc.pdf)。

    • OUTPUT_MODE_DIR の場合、入力ファイルの基本名に出力拡張子を付けた後に s を加えたディレクトリ名が作成されます(例: presentation.pptx -> presentation.pngs/)。これは、複数の画像ファイルが出力される場合(例: PowerPointからPNG画像への変換)に利用されます。

  5. 変換要否の判定 (should_convert):

    • 変換を実行するかどうかを決定するロジックです。

    • overwrite=True の場合は常に変換を実行します。

    • 出力ファイル/ディレクトリが存在しない場合は変換を実行します。

    • update=True かつ入力ファイルの最終更新時刻が出力ファイルの最終更新時刻(ディレクトリの場合はその中の最新ファイル)よりも新しい場合に変換を実行します。これは、ファイルシステムのタイムスタンプ機能を利用した効率的な増分変換を実現します。

    • 最終更新時刻の取得には os.path.getmtime を使用し、ディレクトリの場合は os.walk で中身を走査して最新のタイムスタンプを探します。

  6. 変換処理のラッパー (wrap_... 関数群):

    • プログラムは、docx2pdf, pptx2md2, pandoc.py などの多様な外部Pythonライブラリを利用して実際の変換を行います。

    • これらの外部ライブラリのAPIがそれぞれ異なるため、wrap_simple, wrap_image_to_dir, wrap_pandoc などのラッパー関数が提供されます。これにより、ConverterSpec に登録される converter 関数は一貫したシグネチャ (input_path, output_path, **kwargs) を持ち、内部でライブラリ固有の呼び出しを行います。

    • 一部のラッパーは、ipynb から pdf への変換のように、中間ファイルを生成してから次の変換を呼び出すパイプライン処理を実装しています(例: ipynb -> md -> pdf)。この際、一時ファイルは tempfile モジュールを使用して安全に管理・削除されます。

  7. レジストリの安全なインポート (safe_import_registry):

    • プログラム起動時に、利用可能なすべての変換を ConverterRegistry に登録します。

    • このプロセスは try...except Exception ブロックで各外部ライブラリのインポートを試み、インポートに失敗した場合でもプログラム全体がクラッシュしないように設計されています。エラーは記録され、--list オプションで確認できます。

  8. ファイル名パターンマッチング (matches_target):

    • --target オプションで指定されたパターン(例: *.pptx;*.docx)に基づいて、fnmatch モジュールを使用してファイル名が変換対象であるかを判定します。パターンはセミコロンで区切られます。

これらのメカニズムにより、convert.py は多様なファイル形式間の変換を柔軟かつ堅牢に実行することができます。

必要な非標準ライブラリとインストール方法

convert.py は、特定のファイル形式の変換を実行するために、多数の外部Pythonライブラリに依存しています。すべてのライブラリが必須ではありません。利用したい変換の種類に応じて、必要なライブラリのみをインストールしてください。

また、Pandocを利用した変換(MarkdownからWord/PowerPoint/HTMLなど)を行う場合は、別途Pandoc本体のインストールが必要です。

以下のコマンドでPythonライブラリをインストールできます。

pip install docx2pdf xlsx2pdf pptx2pdf pptx2pdf_with_notes_importable html2pdf_importable md2pdf_importable txt2pdf_importable img2pdf_importable docx2md pptx2md2 pdf2md pptx2img docx2img pdf2img ipynb2md pandoc
  • docx2pdf: Word (.docx) を PDF に変換。

  • xlsx2pdf: Excel (.xlsx) を PDF に変換。

  • pptx2pdf: PowerPoint (.pptx) を PDF に変換。

  • pptx2pdf_with_notes_importable: PowerPoint (.pptx) をスピーカーノート付き PDF に変換。

  • html2pdf_importable: HTML (.html, .htm) を PDF に変換。

  • md2pdf_importable: Markdown (.md) を PDF に変換。

  • txt2pdf_importable: Plain Text (.txt) を PDF に変換。

  • img2pdf_importable: 画像 (.png, .jpg, .jpeg, .bmp, .tif, .tiff, .webp) を PDF に変換。

  • docx2md: Word (.docx) を Markdown に変換(数式/画像抽出を含む)。

  • pptx2md2: PowerPoint (.pptx) を Markdown に変換(数式/画像抽出を含む)。

  • pdf2md: PDF (.pdf) を Markdown に変換。

  • pptx2img: PowerPoint (.pptx) を PNG 画像コレクションに変換。

  • docx2img: Word (.docx) を PNG 画像コレクションに変換。

  • pdf2img: PDF (.pdf) を PNG 画像コレクションに変換。

  • ipynb2md: Jupyter Notebook (.ipynb) または JSON (.json) を Markdown に変換。

  • pandoc: Pythonの pandoc ラッパーライブラリ。MarkdownからWord, PowerPoint, HTMLへの変換にPandoc本体を利用。

    • Pandoc本体のインストール: pandoc PythonライブラリはPandocというコマンドラインツールへのラッパーです。Pandoc本体は別途インストールする必要があります。詳細についてはPandocの公式ウェブサイト(https://pandoc.org/)を参照してください。

必要な入力ファイル

convert.py が処理できる入力ファイルは、登録されている変換ルールによって異なります。以下は、プログラムのソースコードでサポートが試みられている入力ファイル形式のリストです。

  • オフィスドキュメント:

    • .docx (Microsoft Word ドキュメント)

    • .xlsx (Microsoft Excel スプレッドシート)

    • .pptx (Microsoft PowerPoint プレゼンテーション)

  • ウェブ/テキストドキュメント:

    • .html, .htm (HTML ドキュメント)

    • .md (Markdown ドキュメント)

    • .txt (プレーンテキストファイル)

  • 画像ファイル:

    • .png, .jpg, .jpeg, .bmp, .tif, .tiff, .webp (各種画像フォーマット)

  • PDFファイル:

    • .pdf

  • 開発関連ファイル:

    • .ipynb (Jupyter Notebook ファイル)

    • .json (JSONファイル, ipynb2md経由で処理)

入力ファイルに関する注意点:

  • 入力ファイルのパスは、絶対パスまたは root_dir 引数に対する相対パスで指定できます。

  • --target オプションを使用すると、特定のファイル名パターンに一致するファイルのみを変換対象とすることができます。たとえば、--target="*.docx;report*.pptx" のように指定します。

  • xlsx ファイルの場合、~$ で始まる一時ファイル(例: ~$my_sheet.xlsx)は自動的に無視されます。

生成される出力ファイル

convert.py は、指定された変換パスと output_mode に基づいて様々な形式のファイルを出力します。出力ファイルは、デフォルトでは入力ファイルと同じディレクトリに生成されますが、ファイル名が変更されます。

以下は、サポートされている主な出力ファイル形式です。

  • PDFファイル:

    • .pdf (Word, Excel, PowerPoint, HTML, Markdown, Text, Image, Jupyter Notebook/JSONからの変換)

    • .notes.pdf (PowerPointからスピーカーノート付きPDFへの変換)

  • Markdownファイル:

    • .md (Word, PowerPoint, PDF, Jupyter Notebook/JSONからの変換)

      • Markdown変換時に、抽出された画像は通常、出力Markdownファイルと同じディレクトリ内に [元のファイル名].images のような名前のディレクトリ(例: document.md の場合 document.images/)に保存されます。

  • 画像コレクション:

    • .png (PowerPoint, Word, PDFからの変換)

      • これらの変換は OUTPUT_MODE_DIR で登録されており、出力は [元のファイル名].pngs のようなディレクトリ(例: presentation.pptx の場合 presentation.pngs/)になります。このディレクトリ内に、各ページ/スライドに対応する複数のPNG画像ファイルが保存されます。

  • オフィスドキュメント:

    • .docx (MarkdownからWordへの変換)

    • .pptx (MarkdownからPowerPointへの変換)

  • ウェブドキュメント:

    • .html (MarkdownからHTMLへの変換)

出力ファイルに関する注意点:

  • 出力ファイルの命名規則は [入力ファイルの拡張子を除いた部分] + [出力拡張子] です。

  • 出力ディレクトリが指定されている場合 (output_mode=OUTPUT_MODE_DIR)、そのディレクトリは必要に応じて自動的に作成されます。

  • --update オプションが有効な場合、既存の出力ファイルが入力ファイルよりも新しい場合は変換がスキップされます。

  • --overwrite オプションが有効な場合、既存の出力ファイルは常に上書きされます。

コマンドラインでの使用例 (Usage)

convert.py は、コマンドライン引数を使用して動作を制御します。

基本的な構文は以下の通りです。

python convert.py [root_dir] [output_ext] [options]

引数の説明

  • root_dir (オプション):

    • スキャンを開始するルートディレクトリを指定します。デフォルトは現在のディレクトリ (.) です。

  • output_ext (オプション):

    • 目標とする出力ファイルの拡張子を指定します。デフォルトは .pdf です。例: pdf, .notes.pdf, md, png, docx, pptx, html

  • --infile <path>:

    • 再帰検索をスキップし、指定された単一ファイルのみを変換します。

  • --max_level <level>:

    • 再帰の最大深度を指定します。-1 は無制限を意味します(デフォルト)。

  • --target <patterns>:

    • セミコロン (;) で区切られたファイル名パターンを指定し、変換対象をフィルタリングします。例: *.pptx;*.docx

  • --update <0|1>:

    • 1 の場合、出力ファイルが存在し、入力ファイルよりも新しい場合にのみ変換をスキップします。0 の場合、出力ファイルが存在すれば、入力ファイルが新しくてもスキップします。デフォルトは 1 です。

  • --overwrite <0|1>:

    • 1 の場合、タイムスタンプや既存の出力に関わらず、常に変換を実行し既存のファイルを上書きします。デフォルトは 0 です。

  • --pandoc_path <path>:

    • Pandoc実行可能ファイルへのパスを指定します(Pandocベースの変換用)。

  • --template_docx <path>:

    • MarkdownからWordへの変換で使用するPandocのリファレンスドキュメント/テンプレートを指定します。

  • --template_pptx <path>:

    • MarkdownからPowerPointへの変換で使用するPandocのリファレンスドキュメント/テンプレートを指定します。

  • --css <path>:

    • MarkdownからHTMLへの変換で使用するCSSファイルを指定します。

  • --toc <0|1>:

    • 1 の場合、PandocによるWord出力で目次を有効にします。デフォルトは 0 です。

  • --mathml:

    • MarkdownからHTMLへの変換でMathJaxではなくMathMLを使用します。

  • --no_yaml:

    • Pandoc変換に no_yaml オプションを渡します。

  • --verbose:

    • Pandoc変換の詳細モードを有効にします。

  • --smart_conversion <0|1>:

    • pandoc.pysmart_conversion オプションを有効にします。デフォルトは 0 です。

  • --list:

    • 利用可能なすべての変換リストを表示して終了します。

  • --no-pause:

    • プログラム終了時にEnterキーを待たずに終了します。

コマンドラインでの具体的な使用例

ここでは、convert.py の具体的な使用例をいくつか紹介します。

1. 利用可能な変換の一覧表示

インストールされているライブラリに基づいて、convert.py がサポートするすべての変換パスを表示します。

python convert.py --list

実行結果例:

Available converters:
  .docx -> .md [file] (Word to Markdown with equations/images)
  .docx -> .pdf [file] (Word to PDF)
  .docx -> .pngs [dir] (Word to PNG images)
  .htm -> .pdf [file] (HTML to PDF)
  .html -> .pdf [file] (HTML to PDF)
  .ipynb -> .md [file] (Jupyter Notebook to Markdown)
  .ipynb -> .pdf [file] (Jupyter Notebook to PDF via Markdown pipeline)
  .json -> .md [file] (JSON to Markdown)
  .json -> .pdf [file] (JSON to PDF via Markdown pipeline)
  .md -> .docx [file] (Markdown to Word via Pandoc)
  .md -> .html [file] (Markdown to HTML via Pandoc)
  .md -> .pdf [file] (Markdown to PDF)
  .md -> .pptx [file] (Markdown to PowerPoint via Pandoc)
  .pdf -> .md [file] (PDF to Markdown)
  .pdf -> .pngs [dir] (PDF to PNG images)
  .pptx -> .md [file] (PowerPoint to Markdown with equations/images)
  .pptx -> .notes.pdf [file] (PowerPoint to PDF with speaker notes)
  .pptx -> .pdf [file] (PowerPoint to PDF)
  .pptx -> .pngs [dir] (PowerPoint to PNG images)
  .txt -> .pdf [file] (Text to PDF)
  .xlsx -> .pdf [file] (Excel to PDF)
  ... (他の画像形式からPDFへの変換など)

2. ディレクトリ内のすべてのWordドキュメントをPDFに変換

現在のディレクトリとそのサブディレクトリにあるすべての .docx ファイルを .pdf に変換します。既存のPDFが入力より古い場合は更新します。

python convert.py . pdf --target="*.docx"

実行結果例:

Searching in '/path/to/current/directory'
Target output format: .pdf
Max level: -1
update: 1
overwrite: 0
Target patterns: *.docx

Converting: '/path/to/current/directory/report.docx' -> '/path/to/current/directory/report.pdf' (output does not exist)
Converting: '/path/to/current/directory/documents/memo.docx' -> '/path/to/current/directory/documents/memo.pdf' (source is newer than output)
Skipping: '/path/to/current/directory/old_doc.docx' (up to date)

Conversion process finished.
Scanned supported files: 3
Converted files: 2

Program execution completed.
Press ENTER to terminate>>

3. 単一のJupyter NotebookをPDFに変換(上書き指定)

my_notebook.ipynb をPDFに変換し、既存の my_notebook.pdf があっても強制的に上書きします。

python convert.py --infile my_notebook.ipynb .pdf --overwrite 1

実行結果例:

Single-file mode: /path/to/my_notebook.ipynb
Converting: '/path/to/my_notebook.ipynb' -> '/path/to/my_notebook.pdf' (overwrite=1)

Conversion process finished.
Scanned supported files: 1
Converted files: 1

Program execution completed.
Press ENTER to terminate>>

4. MarkdownファイルをWordドキュメントに変換(Pandoc利用)

my_document.md をPandocを使用してWordドキュメントに変換します。カスタムのリファレンスドキュメント (my_template.docx) を使用し、目次を有効にします。Pandoc実行ファイルがシステムのPATHにない場合は --pandoc_path で指定します。

python convert.py --infile my_document.md .docx --template_docx my_template.docx --toc 1 --pandoc_path /usr/local/bin/pandoc

実行結果例:

Single-file mode: /path/to/my_document.md
Converting: '/path/to/my_document.md' -> '/path/to/my_document.docx' (output does not exist)

Conversion process finished.
Scanned supported files: 1
Converted files: 1

Program execution completed.
Press ENTER to terminate>>

5. PowerPointプレゼンテーションをPNG画像コレクションに変換

presentations/project.pptx をPNG画像コレクションに変換します。出力は presentations/project.pngs/ ディレクトリに保存されます。

python convert.py --infile presentations/project.pptx .png

実行結果例:

Single-file mode: /path/to/presentations/project.pptx
Converting: '/path/to/presentations/project.pptx' -> '/path/to/presentations/project.pngs' (output does not exist)

Conversion process finished.
Scanned supported files: 1
Converted files: 1

Program execution completed.
Press ENTER to terminate>>