いろいろ備忘録日記

主に .NET とか Go とか Flutter とか Python絡みのメモを公開しています。

Pythonメモ-55 (pygments でシンタックスハイライトさせて遊ぶ) (pygments, pygmentize, syntax highlight)

概要

何かのライブラリをインストールしようとすると、ちょこちょこ見る名前って結構あります。

私の場合、pygments ってライブラリがよく出てきていたのですが

これが何なのか知りませんでした(恥

Welcome! — Pygments

とっても有名なライブラリなんですね。

何の機能を持っているかというと プログラムコードなどに対して シンタックスハイライト してくれるというものです。

よくあちこちのブログとかで見る、あのハイライト状態な出力を行ってくれます。

300以上の言語に対応しているとのこと。すごい!

出力も HTML画像 とかいろいろ選べる模様。

インストール

conda の場合は、いつものように

$ conda install pygments

で終わりです。Anaconda使っている場合は、最初からインストールされています。

基本的な使い方

とりあえず、ドキュメントをちょっと見てみたら、使い方としては以下のようにするみたい。

  • ハイライト対象のデータを用意する

  • 構文解析器 (Lexer) を選んで生成

  • 出力するもの (Formatter) を選んで生成

  • pygments.highlight 関数に渡して出力してもらう

みたいです。

以下のような感じ。python3の構文でHTMLでシンタックスハイライトする場合の基本的なやり方。

# データ 用意
code = """\
def hello():
    print('hello world')
    for x in range(10):
        print(x)
"""

# Lexer 用意
lexer = pygments.lexers.python.Python3Lexer()

# Formatter 用意
formatter = pygments.formatters.html.HtmlFormatter()

# 出力
html = pygments.highlight(code, lexer, formatter)

上のように直接 具象クラス を使ってもいいですが

ヘルパー関数があるのでそれ使ったほうが良さそう。

# データ 用意
code = """\
def hello():
    print('hello world')
    for x in range(10):
        print(x)
"""

# Lexer 用意
lexer = pygments.lexers.get_lexer_by_name('python3')

# Formatter 用意
formatter = pygments.formatters.get_formatter_by_name('html')

# 出力
html = pygments.highlight(code, lexer, formatter)

サンプル

以下、サンプルです。

"""
pygments に関するサンプルです。
最も基本的な使い方を記載しています。

- pythonからpygmentsの操作方法
- pygmentize コマンドの使い方(コメントで)
"""
import os
import subprocess

from pygments import highlight
from pygments.formatters import get_formatter_by_name
from pygments.lexers import get_lexer_by_name

from common.commoncls import SampleBase
from common.commonfunc import pr


class Sample(SampleBase):
    """
    pygmentsのサンプルです。
    pythonのコードをハイライト付きでhtmlに出力します。
    """

    def exec(self):
        """処理を実行します。"""
        # --------------------------------------------------------------------------------
        # pygments の基本的な使い方
        #   - http://pygments.org/
        #
        # pygments を利用する場合、必要なオブジェクトは以下の3つ
        #   - コード: ハイライト表示対象のコード
        #   - 解析器(lexer): コードを解析するためのオブジェクト
        #   - フォーマッタ: 最終的な出力を担当するオブジェクト
        #
        # lexer と formatter は、各実装クラスを直接つかってもいいが
        # 以下のヘルパー関数を使用しても取得できる
        #   - pygments.lexers.get_lexer_by_name()
        #     - 例えば、言語が python の場合は、"python" or "python3" となる
        #     - http://pygments.org/docs/lexers/
        #   - pygments.formatters.get_formatter_by_name()
        #     - 例えば、HTMLで出力したい場合は "html" となる
        #     - http://pygments.org/docs/formatters/
        #     - HtmlFormatterは便利だが、残念な事にHTML4形式で現状出力されてしまう。
        #
        # 必要なオブジェクトが揃ったら、後は pygments.highlight() に渡すと
        # 整形データが取得できる
        # --------------------------------------------------------------------------------
        code = """\
def hello():
    print('world')
    results = []
    for x in range(10):
        ressults.append(i for i in x)
        """
        lexer = get_lexer_by_name('python3')
        formatter = get_formatter_by_name('html', linenos=True, full=True, encoding='utf-8')

        # formatter に対して, 共通パラメータ [encoding] を指定した場合
        # 結果として受け取るデータの型は、bytes になる。指定していない場合、str となる。
        # HtmlFormatter にて encoding を指定しない場合、 charset の値が None となることに注意。
        html = highlight(code, lexer, formatter)
        if hasattr(html, 'decode'):
            html = html.decode('utf-8')
        pr('pygments.html', html)

        file_path = '/tmp/pygments_test.html'
        with open(file_path, 'w') as out_fp:
            out_fp.write(html)

        preserve_file = True
        try:
            subprocess.check_call(file_path, shell=True)
        finally:
            if not preserve_file:
                os.unlink(file_path)

        # --------------------------------------------------------------------------------
        # pygmentize コマンドの利用
        # pygments をインストールすると pygmentize という専用コマンドもインストールされる。
        # このコマンドを利用すると、pythonスクリプトを書かなくてもハイライト付きのデータが取得できる。
        #
        # 上のコードと同じような出力を得る場合は以下のようにする
        # $ pygmentize -f html -O linenos,full -o /tmp/pygments_test.html hello.py
        # --------------------------------------------------------------------------------


def go():
    """サンプルを実行します。"""
    obj = Sample()
    obj.exec()


if __name__ == '__main__':
    go()

try-python/pygments01.py at master · devlights/try-python · GitHub

pygmentize コマンド

pygmentsをインストールすると、pygmentizeというコマンドもインストールされます。

このコマンドは、いちいちスクリプト書かなくても、上のサンプルの動きと同じようなことをやってくれます。

さくっとハイライトした出力物を生成したい場合は、このコマンドでつくって渡した方が楽ですね。

上のサンプルと同じような出力を得る場合は、以下のようにします。

$ pygmentize -f html -O linenos,full -o /tmp/pygments_test.html hello.py

参考情報


過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。