0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

要望はないかもしれませんが、ソースコードを行番号付きでPDFにする

Last updated at Posted at 2025-07-12

ソースコード(テキスト)を行番号付きでPDFにするプログラムです。あまり用途はなさ王ですが、pythonからPDFにする勉強のために作成しました。python3 code2pdf.py <ソースコード> -o <出力先> で動きます。

環境

  • ubuntu 24
  • python3
  • python fpdf2
  • Unicode フォント

Unicode フォントのインストール

広範囲のUnicodeをカバーする「No Tofu」フォントファミリーをインストールします。

sudo apt install fonts-noto-cjk

fpdf2 のインストール

pip install fpdf2

ソースコードをPDFに変換するプログラム

ヘッダとフッターを付けるためFPDFクラスを継承してPDFクラスを作成しました。

PDF クラス

PDFクラスのコンストラクタでUnicodeフォントを設定しています。ヘッダにファイル名、フッターにページ番号の表示が入ってます。

ファイルの読み込みとPDF化

ファイルを読み込んで、行番号をつけるために、1行ごとに処理をしています。
行番号をPDF出力してから読み込んだ行を出力しています。

fpdf2は、デフォルトで{nb}が総ページ数に置き換わるようになってました。ソースコードに「{nb}」があると総ページ数に置き換わるため、{nb}{\0nb}に変換しました。どのように変換するのかが不明ですが、{\0nb}へ変換するので表示はできるようになりました。
もしかしたら、何が弊害があるかもしれませんが、とりあえずこれで進めました。

code2pdf.py
#!/usr/bin/env python3

import argparse
import fpdf
import os
import re


parser = argparse.ArgumentParser(description='Convert code to PDF')
parser.add_argument('file',
                    help='input file')
parser.add_argument('-o', '--output',
                    default='output.pdf',
                    help='output file (default is output.pdf)')
args = parser.parse_args()


class PDF(fpdf.FPDF):
    def __init__(self, header_text):
        self.header_text = header_text
        super().__init__(orientation='portrait', unit='mm', format='A4')
        self.set_margins(left=10, top=20, right=10)
        self.set_auto_page_break(auto=True, margin=20)
        self.add_font(
                family='Noto Sans Mono CJK JP',
                style='',
                fname='/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc')
        self.set_font('Noto Sans Mono CJK JP', size=8)
        self.add_page()

    def centering(self, y, text):
        org_y = self.get_y()
        self.set_y(y)
        self.cell(w=0, text=text, align='C')
        self.set_y(org_y)

    def header(self):
        self.centering(y=10,
                       text=self.header_text)

    def footer(self):
        self.centering(y=-10-self.font_size_pt/self.k,
                       text=f'Page {self.page_no()} of {{nb}}')


pdf = PDF(header_text=os.path.basename(args.file))
with open(args.file, 'r', encoding='utf-8') as f:
    for i, line in enumerate(f.readlines(), start=1):
        pdf.cell(w=10, h=None, text=f'{i}', align='R')
        # Fixed an issue where "{nb}" was replaced with the total page number
        line = re.sub(r'{nb}', '{\0nb}', line)
        pdf.multi_cell(w=0, h=None, text=line, new_y='LAST')

pdf.output(args.output)

さいごに

少ないコードで、python からPDFを作成できるのが分かりました。何かの参考になればと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?