converter.pandoc のソースコード

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Pandoc専用:MarkdownのWord/PowerPoint/HTML変換とテンプレート生成。

このモジュールは、Pandocツールを利用してMarkdownファイルを様々な形式(Word, PowerPoint, HTML)に変換するためのユーティリティを提供します。
また、Pandocで使用するテンプレートファイルの生成機能も備えています。

- AI処理は一切ありません(tkai_lib不要)

**使用例:**

    # テンプレート生成
    python pandoc_convert.py --make_template docx --template template_textbook.docx
    python pandoc_convert.py --make_template pptx --template template_slide.pptx

    # 変換
    python pandoc_convert.py --convert docx --infile lecture_textbook.md --template template_textbook.docx
    python pandoc_convert.py --convert pptx --infile lecture_slide.md --template template_slide.pptx
    python pandoc_convert.py --convert html --infile lecture_textbook.md --mathml
    python pandoc_convert.py --convert html --infile lecture_textbook.md --css custom_style.css

関連リンク:
    :doc:`pandoc_usage`
"""

import os
import sys
import argparse
from pathlib import Path
import re
import yaml
import shutil
import platform
import subprocess
from pathlib import Path
import chardet

pause = 0

[ドキュメント] def terminate(): """ プログラムを終了する。 詳細説明: グローバル変数 `pause` が真の場合、ユーザーにEnterキーの入力を要求してからプログラムを終了します。 これにより、コンソールウィンドウがすぐに閉じられるのを防ぎ、出力の確認を可能にします。 """ if pause: input("\nPress ENTER to terminate\n") exit()
[ドキュメント] def find_pandoc() -> str | None: """ pandoc 実行ファイルのパスを探す。 詳細説明: 以下の優先順位でpandoc実行ファイルを探索します。 1. 環境変数 `pandoc_path` で指定されたパス。 2. 環境変数 `tkProg_path` に基づく既定の配置パス。 - Windows: `{tkProg_path}/tkApp_Win/pandoc/pandoc.exe` - Linux/macOS: `{tkProg_path}/tkApp_Linux/pandoc/pandoc` 3. システムの `PATH` 環境変数に登録されているパス。 いずれの場所でも見つからなかった場合は `None` を返します。 :returns: str | None: pandoc実行ファイルのパス。見つからない場合はNone。 """ # 1. 環境変数 pandoc_path env_pandoc = os.environ.get("pandoc_path") if env_pandoc and os.path.isfile(env_pandoc): return env_pandoc # 2. tkProg_path 内 tkprog = os.environ.get("tkProg_path") if tkprog is None: script_dir = Path(sys.argv[0]).resolve().parent tkprog = (script_dir / "../../").resolve() if tkprog: if platform.system() == "Windows": candidate = os.path.join(tkprog, "tkApp_Win", "pandoc", "pandoc.exe") else: candidate = os.path.join(tkprog, "tkApp_Linux", "pandoc", "pandoc") if os.path.isfile(candidate): return candidate # 3. PATH から探す exe_name = "pandoc.exe" if platform.system() == "Windows" else "pandoc" path = shutil.which(exe_name) if path: return path return "pandoc"
[ドキュメント] def find_template(template_path: str) -> str | None: """ テンプレートファイルのパスを解決する。 詳細説明: 与えられた `template_path` を以下の順序で探し、最初に見つかったファイルのフルパスを返します。 1. スクリプトが実行されているカレントディレクトリ。 2. このスクリプトファイルが存在するディレクトリ。 どの場所でもファイルが見つからない場合は、`template_path` をそのまま返します。 :param template_path: str: テンプレートファイルのパスまたはファイル名。 :returns: str | None: 見つかったテンプレートファイルのフルパス、またはファイルが見つからない場合は元のパス。 """ if not template_path: return None # 1. 実行ディレクトリ(カレント) candidate1 = Path.cwd() / template_path if candidate1.is_file(): return str(candidate1.resolve()) # 2. スクリプトのあるディレクトリ script_dir = Path(sys.argv[0]).resolve().parent candidate2 = script_dir / template_path if candidate2.is_file(): return str(candidate2.resolve()) # 見つからなければ None return template_path
[ドキュメント] def parse_args(): """ コマンドライン引数を解析する。 詳細説明: `argparse` モジュールを使用して、Pandocユーティリティのコマンドライン引数を定義し、解析します。 Pandoc実行ファイルのパス、入力/出力ファイル、テンプレート、変換形式、HTML/CSSオプション、 テンプレート生成オプションなどをサポートします。また、`find_template` を使ってテンプレートパスを解決します。 :returns: tuple[argparse.ArgumentParser, argparse.Namespace]: パーサーオブジェクトと解析された引数オブジェクトのタプル。 """ pandoc_path = find_pandoc() print(f"✅ pandoc found: {pandoc_path}") p = argparse.ArgumentParser( description="Pandocユーティリティ(テンプレート生成 & 変換専用)", formatter_class=argparse.RawTextHelpFormatter ) p.add_argument('--pandoc_path', "-p", default=pandoc_path, help=f'pandoc 実行ファイルのパス (デフォルト {pandoc_path})') p.add_argument('--infile', "-i", help='変換元Markdown(--convert使用時に指定)') p.add_argument('--outfile', "-o", type=str, default = None, help='出力ファイル名n(デフォルト --convertから拡張子を設定)') p.add_argument('--template', "-t", default = None, help='変換に使用、または作成するテンプレートファイルのパス') p.add_argument('--convert', "-c", choices=['docx', 'pptx', 'html', ''], help='Pandoc変換を実行') p.add_argument('--toc', type=int, default=0, help='入力を markdown-yaml_metadata_block として解釈する') p.add_argument('--mathml', action='store_true', help='HTML変換時にMathMLを使って数式を表示') p.add_argument('--css', help='HTML変換時のカスタムCSS') p.add_argument('--make_template', choices=['docx', 'pptx'], help='デフォルトテンプレートを出力して終了') p.add_argument('--smart_conversion', type=int, default=0, help='自動変換 (--を-に変換するなど) する') p.add_argument('--no-yaml', action='store_true', help='入力を markdown-yaml_metadata_block として解釈する') p.add_argument('--verbose', action='store_true', help='詳細出力') p.add_argument("--pause", type=int, default=0, help="終了時にENTERキー入力を要求するか (デフォルト: 0)") """ p.add_argument( '--pandoc_path', default=None, help='pandoc 実行ファイルのパス' ) p.add_argument( '--template', default=None, help='pandoc 用テンプレート (docx/pptx)' ) p.add_argument( '--toc', action='store_true', help='pandoc: --toc' ) p.add_argument( '--css', default=None, help='pandoc: HTML 用 CSS' ) """ args = p.parse_args() if args.template: args.template = find_template(args.template) print(f"✅ template found: {args.template}") return p, args
[ドキュメント] def run_command(cmd: list) -> bool: """ 指定されたコマンドを実行し、その成否を返す。 詳細説明: `subprocess.run` を使ってコマンドを実行します。 コマンドが正常に完了したか、ファイルが見つからないか、またはその他のエラーが発生したかを判定し、 結果に応じて適切なメッセージをコンソールに出力します。 :param cmd: list: 実行するコマンドとその引数を要素とするリスト。 :returns: bool: コマンドが正常に完了した場合はTrue、それ以外はFalse。 """ print(f"⚡️ 実行中: {' '.join(cmd)}") try: _ = subprocess.run(cmd, check=True, capture_output=True, text=True, encoding='utf-8') print("✅ コマンドは正常に完了しました。") return True except FileNotFoundError: print(f"❌ '{cmd[0]}' が見つかりません。Pandocはインストール済みでPATHが通っていますか?", file=sys.stderr) except subprocess.CalledProcessError as e: print(f"❌ Pandoc実行エラー (終了コード: {e.returncode})", file=sys.stderr) print(f"--- stderr ---\n{e.stderr}\n--------------", file=sys.stderr) return False
[ドキュメント] def extract_yaml_front_matter(md_text: str): """ Markdownテキストの先頭からYAMLフロントマターを抽出する。 詳細説明: Markdownファイルの冒頭に `---\n<YAML内容>\n---` の形式で記述されたYAMLフロントマターを正規表現で検索し、 その内容を文字列として返します。見つからない場合はNoneを返します。 :param md_text: str: Markdown形式のテキスト。 :returns: str | None: 抽出されたYAMLフロントマターの文字列。見つからない場合はNone。 """ pattern = r'^---\s*\n(.*?)\n---\s*\n' match = re.match(pattern, md_text, re.DOTALL) if not match: return None return match.group(1)
[ドキュメント] def is_valid_yaml(yaml_text: str) -> bool: """ 与えられた文字列が有効なYAML形式であるかを判定する。 詳細説明: `yaml.safe_load` を使用して文字列をパースを試みます。 パース中に例外が発生しなければ有効なYAMLと判断しTrueを返します。 それ以外の場合はFalseを返します。 :param yaml_text: str: YAML形式であるかを確認する文字列。 :returns: bool: 有効なYAMLであればTrue、そうでなければFalse。 """ try: yaml.safe_load(yaml_text) return True except Exception: return False
[ドキュメント] def read_text_with_chardet(path: str) -> str | None: """ ファイルの文字コードを自動推定し、テキストとして読み込む。 詳細説明: まずファイルをバイナリモードで読み込み、`chardet` ライブラリを使用して文字コードを推定します。 推定された文字コードでファイルをデコードし、その内容を文字列として返します。 推定に失敗した場合やデコードエラーが発生した場合は、エラーメッセージを出力しNoneを返します。 推定されたエンコーディングがNoneの場合、またはデコードエラーが発生した場合は、'utf-8' を試行します。 :param path: str: 読み込むファイルのパス。 :returns: str | None: ファイルの内容を文字列として返す。ファイルの読み込みに失敗した場合はNone。 """ # まずバイナリで読み込んで文字コードを推定 if not os.path.isfile(path): return None with open(path, "rb") as fb: raw = fb.read() result = chardet.detect(raw) encoding = result["encoding"] confidence = result["confidence"] if encoding is None: print(f"Failed to detect encoding: {encoding}") print(f" Try utf-8") encoding = 'utf-8' else: print(f"Detected encoding: {encoding} (confidence={confidence}) for {path}") # 推定した文字コードでデコード(失敗しにくいように errors='replace' も可) try: text = raw.decode(encoding, errors="replace") except: print(f"Error in read_text_with_chardet(): Failed to encode with {encoding}") return None return text
[ドキュメント] def correct_markdown_pandoc_error(md_text: str, base_dir: Path = None) -> str: """ Pandocがエラーを出す典型的なMarkdownの記述を自動修正する。 詳細説明: この関数は、Pandocでの変換時に問題を引き起こしやすいMarkdownのパターンを検出し、修正します。 主な修正内容は以下の通りです。 - **YAMLフロントマターの安全化**: Markdownの冒頭にある`---`ブロックがYAMLとして不正な場合、 Pandocが誤ってYAMLと認識しないよう、その前後に空行を追加して無効化します。 有効なYAMLフロントマターは変更しません。 - **水平線 (`---`) の安全化**: YAMLフロントマター以外の単独の`---`が水平線として機能する場合、 その前後に空行を追加して、他の要素との境界を明確にし、Pandocの解釈ミスを防ぎます。 - **存在しない画像・リンクの無害化**: `base_dir`が指定されている場合、Markdown内の画像やリンクが 示すファイルパスが実際に存在しない場合に、Pandocがエラーを出すのを防ぐため、 該当するMarkdownの記述をバッククォートで囲み、コードとして扱うように修正します。 - **ブロック数式 `$$ inline $$` の正規化**: Pandocが正しく解釈できるよう、 `$$ 数式 $$` の形式で書かれたインライン風のブロック数式を、 複数行のブロック数式形式 `$$\n数式\n$$` に正規化します。 - **生成AIが生成しがちな数式記述の変換**: `\[ ... \]` や `\( ... \)` といったTeX/LaTeX形式の数式記述を、 Pandocが確実に読める `$$\n...\n$$` のブロック形式に変換します。 :param md_text: str: 修正対象のMarkdownテキスト。 :param base_dir: Path | None: 画像などの相対パスを解決するためのベースディレクトリ。 指定しない場合、ファイル存在チェックは行われません。デフォルトはNone。 :returns: str: 修正されたMarkdownテキスト。 """ # ============================================================ # 1. YAML フロントマターの判定 # ============================================================ yaml_block = extract_yaml_front_matter(md_text) if yaml_block is not None: if is_valid_yaml(yaml_block): # 本物の YAML → 何もしない pass else: # YAML として不正 → pandoc が誤判定するので空行を追加して無効化 md_text = md_text.replace("---", "\n---\n", 1) # ============================================================ # 2. 単独の --- の前後に空行を追加(YAML 以外) # ============================================================ lines = md_text.splitlines() fixed_lines = [] for i, line in enumerate(lines): if line.strip() == "---": # YAML フロントマター以外の --- を安全化 if i > 0 and lines[i-1].strip() != "": fixed_lines.append("") fixed_lines.append(line) if i < len(lines)-1 and lines[i+1].strip() != "": fixed_lines.append("") else: fixed_lines.append(line) md_text = "\n".join(fixed_lines) # ============================================================ # 3. 存在しない画像・リンクを無害化 # ============================================================ def replace_if_missing(match): full = match.group(1) path = match.group(2) if base_dir is None: return full file_path = (base_dir / path).resolve() if not file_path.exists(): # pandoc が落ちるのでコード化 return f"`{full}`" return full pattern = r'(!?\[.*?\]\((.*?)\))' md_text = re.sub(pattern, replace_if_missing, md_text) # ============================================================ # 4. $$ inline $$ → ブロック数式に正規化 # ============================================================ def normalize_inline_math(match): content = match.group(1).strip() # すでに複数行ならそのままブロック化 return f"$$\n{content}\n$$" math_pattern = r'\$\$(.+?)\$\$' md_text = re.sub(math_pattern, normalize_inline_math, md_text, flags=re.DOTALL) # ============================================================ # 5. $[ ... ]$ → $$ ... $$ に変換(生成AI対策) # ============================================================ def convert_ai_math(match): content = match.group(1).strip() return f"$$\n{content}\n$$" # ai_math_pattern = r'\$\[\s*(.+?)\s*\]\$' # $[ ... ]$ # md_text = re.sub(ai_math_pattern, convert_ai_math, md_text, flags=re.DOTALL) # ai_math_pattern = r'\$\(\s*(.+?)\s*\)\$' # $( ... )$ # md_text = re.sub(ai_math_pattern, convert_ai_math, md_text, flags=re.DOTALL) ai_math_pattern = r'\\\[\s*(.+?)\s*\\\]' # \[ ... \] md_text = re.sub(ai_math_pattern, convert_ai_math, md_text, flags=re.DOTALL) ai_math_pattern = r'\\\(\s*(.+?)\s*\\\)' # \( ... \) md_text = re.sub(ai_math_pattern, convert_ai_math, md_text, flags=re.DOTALL) return md_text
[ドキュメント] def make_pandoc_template(pandoc_path: str, fmt: str, template_file: str): """ Pandocのデフォルトテンプレートファイルを生成する。 詳細説明: 指定されたフォーマット(docxまたはpptx)に対応するPandocのデフォルト参照ドキュメントを `--print-default-data-file` オプションを使用して出力します。 生成されたファイルは、ユーザーがカスタムスタイルを定義するためのベースとして利用できます。 :param pandoc_path: str: Pandoc実行ファイルのパス。 :param fmt: str: 生成するテンプレートのフォーマット ('docx'または'pptx')。 :param template_file: str: 出力するテンプレートファイルのパス。 """ print(f"🎨 {fmt.upper()} 用のPandocテンプレートを作成します...") data_file = 'reference.docx' if fmt == 'docx' else 'reference.pptx' cmd = [pandoc_path, '-o', template_file, f'--print-default-data-file={data_file}'] if run_command(cmd): print(f"📄 テンプレート '{template_file}' を作成しました。編集してスタイルを調整してください。")
[ドキュメント] def correct_html(outfile: str): """ Pandocが生成したHTMLファイルをMathJax対応の完全なHTMLドキュメントに修正する。 詳細説明: Pandocが `--mathml` オプションなしで生成したHTMLは、MathJaxを読み込むためのスクリプトや HTMLヘッダー/フッターが欠けている場合があります。この関数は、指定されたHTMLファイルを読み込み、 MathJax CDNスクリプトを含むHTML5の基本的な構造(`<!DOCTYPE html>`, `<html>`, `<head>`, `<body>`)でラップし、 再保存することで、ブラウザで正しく表示されるようにします。 :param outfile: str: 修正対象のHTMLファイルのパス。 """ with open(outfile, 'r', encoding='utf-8') as f: body_content = f.read() # MathJax対応のHTMLとしてラップ html_template = f"""<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script> <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/mml-chtml.js"></script> </head> <body> {body_content} </body> </html> """ with open(outfile, 'w', encoding='utf-8') as f: f.write(html_template)
[ドキュメント] def convert_with_pandoc(pandoc_path: str, target: str, infile_md: str, outfile: str, template: str = None, css: str = None, no_yaml: bool = False, args: argparse.Namespace = None): """ Pandocを使ってMarkdownファイルを指定された形式に変換する。 詳細説明: この関数は、入力Markdownファイルを指定されたターゲット形式(docx, pptx, html)に変換するために、 Pandocコマンドラインツールを呼び出します。 出力ファイルパスの決定、参照テンプレート(docx/pptx)、カスタムCSS(html)、 目次生成、MathMLサポート、YAMLフロントマターの処理など、様々な変換オプションをサポートします。 HTML変換の場合、`correct_html` を呼び出してMathJax対応の最終処理を行います。 :param pandoc_path: str: Pandoc実行ファイルのパス。 :param target: str: 変換ターゲットフォーマット ('docx', 'pptx', 'html')。 :param infile_md: str: 入力Markdownファイルのパス。 :param outfile: str: 出力ファイルのパス。指定しない場合、入力ファイル名から推測される。 :param template: str | None: 参照テンプレートファイルのパス。docx/pptx変換時に使用。デフォルトはNone。 :param css: str | None: HTML変換時に使用するカスタムCSSファイルのパス。デフォルトはNone。 :param no_yaml: bool: YAMLフロントマターをmarkdown-yaml_metadata_blockとして解釈するかどうか。 Trueの場合、PandocはYAMLブロックを特殊なものとして扱わない。デフォルトはFalse。 :param args: argparse.Namespace: `parse_args` によって解析された全ての引数オブジェクト。 `toc`, `mathml`, `verbose`, `smart_conversion`, `convert` などのフラグを含む。 """ print() print(f"🔄 '{infile_md}' → {target.upper()} 変換を開始します...") if not Path(infile_md).exists(): print(f"❌ 入力Markdown '{infile_md}' が存在しません。", file=sys.stderr) terminate() print(f"target : {target}") print(f"template: {template}") if outfile is None or outfile == '': outfile = str(Path(infile_md).with_suffix(f'.{target}')) # ベース引数 if no_yaml: cmd = [pandoc_path, infile_md, '-o', outfile, '-f', 'markdown-yaml_metadata_block'] else: cmd = [pandoc_path, infile_md, '-o', outfile] if args.toc and outfile.endswith(".docx"): cmd.append('--toc') if args.mathml: cmd.append('--mathml') if args.verbose: cmd.append('--verbose') if not args.smart_conversion: cmd.extend(['-f', 'markdown-smart']) # 出力形式ごとの追加 if target == 'html': if css: cmd.extend(['--css', css]) elif target in ('docx', 'pptx'): if not template: pass # print("❌ --convert docx/pptx では --template が必須です。", file=sys.stderr) # sys.exit(1) elif f".{target}" in template: cmd.extend(['--reference-doc', template]) # if target == 'pptx': # cmd.extend(['-t', 'pptx']) cmd.extend(['-t', target]) print("cmd:", cmd) ret = run_command(cmd) if ret: if args.convert == 'html': correct_html(outfile) print(f"📑 変換後のファイル '{outfile}' を作成しました。")
[ドキュメント] def convert_md( infile_md: str, target: str, # 'docx' | 'pptx' | 'html' pandoc_path: str, # ← 明示的に渡す outfile: str = None, template: str = None, toc: bool = False, css: str = None, mathml: bool = False, no_yaml: bool = False, verbose: bool = False, smart_conversion: int = 0, ) -> bool: """ Markdownファイルをdocx、pptx、またはhtml形式に変換するライブラリAPI。 詳細説明: この関数は、コマンドライン引数ではなくPythonの関数呼び出しとしてPandocの変換機能を提供します。 指定されたMarkdownファイルを読み込み、`correct_markdown_pandoc_error` で前処理を行った後、 `convert_with_pandoc` を呼び出して実際の変換を実行します。 修正されたMarkdownは一時ファイルに書き出され、変換後にPandocによって使用されます。 :param infile_md: str: 入力Markdownファイルのパス。 :param target: str: 変換ターゲットフォーマット ('docx', 'pptx', 'html')。 :param pandoc_path: str: Pandoc実行ファイルのパス。 :param outfile: str | None: 出力ファイルのパス。指定しない場合、入力ファイル名から推測される。デフォルトはNone。 :param template: str | None: 参照テンプレートファイルのパス。docx/pptx変換時に使用。デフォルトはNone。 :param toc: bool: 目次を生成するかどうか。デフォルトはFalse。 :param css: str | None: HTML変換時に使用するカスタムCSSファイルのパス。デフォルトはNone。 :param mathml: bool: HTML変換時にMathMLを使って数式を表示するかどうか。デフォルトはFalse。 :param no_yaml: bool: YAMLフロントマターをmarkdown-yaml_metadata_blockとして解釈しないかどうか。デフォルトはFalse。 :param verbose: bool: 詳細出力を有効にするかどうか。デフォルトはFalse。 :param smart_conversion: int: 自動変換 (--を-に変換するなど) を行うかどうか (0: 無効, 1: 有効)。デフォルトは0。 :returns: bool: 変換が成功した場合はTrue。 :raises RuntimeError: ファイルの読み込みに失敗した場合。 """ class DummyArgs: pass args = DummyArgs() args.toc = toc args.mathml = mathml args.verbose = verbose args.convert = target args.smart_conversion = smart_conversion # convert_with_pandocに渡すために追加 # read & normalize markdown md_text = read_text_with_chardet(infile_md) if md_text is None: raise RuntimeError(f"Failed to read {infile_md}") corrected = correct_markdown_pandoc_error( md_text, base_dir=Path(infile_md).parent ) corrected_path = Path(infile_md).with_suffix(".corrected.md") corrected_path.write_text(corrected, encoding="utf-8") convert_with_pandoc( pandoc_path=pandoc_path, target=target, infile_md=str(corrected_path), outfile=outfile, template=template, css=css, no_yaml=no_yaml, args=args, ) return True
[ドキュメント] def main(): """ スクリプトのメインエントリポイント。 詳細説明: コマンドライン引数を解析し、それに基づいてPandoc関連の操作(テンプレート生成またはファイル変換)を実行します。 Pandoc実行ファイルの存在チェックや、必要な引数が指定されているかの検証も行います。 処理が完了した後、またはエラーが発生した場合、`terminate()` 関数を呼び出してプログラムを終了します。 :returns: None """ global pause parser, args = parse_args() pause = args.pause print() print(f"{args.pandoc_path=}") if args.pandoc_path == "": print(f"Error: pandoc実行ファイルを引数 pandoc_path で設定してください") terminate() if not os.path.exists(args.pandoc_path): print(f"Error: pandoc実行ファイル [{args.pandoc_path}] が見つかりません") terminate() if args.convert == '': target = os.path.splitext(args.outfile)[1].lstrip('.') else: target = args.convert print(f"{args.infile=}") print(f"{args.outfile=}") print(f"{args.template=}") print(f"{target=}") print(f"{args.toc=}") print(f"{args.pause=}") # 1) テンプレート生成(最優先) if args.make_template: if not args.template: parser.error("--make_template には --template で出力先ファイル名が必要です。") make_pandoc_template(args.pandoc_path, args.make_template, args.template) terminate() # 2) 変換 if args.convert or args.outfile: if not args.infile: parser.error("--convert を使うときは --infile(Markdown)を指定してください。") md_text = read_text_with_chardet(args.infile) if md_text: text_corrected = correct_markdown_pandoc_error(md_text, base_dir = None) corrected_path = Path(args.infile).with_suffix(".corrected.md") with open(corrected_path, "w", encoding="utf-8") as fp: fp.write(text_corrected) else: corrected_path = args.infile convert_with_pandoc( args.pandoc_path, target, str(corrected_path), args.outfile, template=args.template, css=args.css, no_yaml=args.no_yaml, args = args, ) terminate() # 3) どちらも指定がない場合 print("\nError: --convertか--outfileを指定してください") parser.print_help()
if __name__ == "__main__": main() terminate()