Pythonで文字列を折り返し・切り詰めして整形するtextwrap

Modified: | Tags: Python, 文字列

Pythonで文字列を任意の文字数で折り返し(改行)、切り詰め(省略)して整形するには、標準ライブラリのtextwrapモジュールを使う。

出力時ではなくコード中の長い文字列を複数行に改行して書く場合は以下の記事を参照。

文字列ではなくリストや辞書を整形して出力するにはpprintモジュールが便利。

本記事のサンプルコードでは以下のようにtextwrapモジュールをインポートしている。標準ライブラリに含まれているのでインストールは不要。

import textwrap

文字列を折り返し(改行): wrap(), fill()

textwrapモジュールのwrap()関数で、任意の文字数に収まるように単語の区切りで分割したリストが取得できる。

第一引数に対象の文字列、第二引数widthに文字数を指定する。デフォルトはwidth=70

s = "Python can be easy to pick up whether you're a first time programmer or you're experienced with other languages"

s_wrap_list = textwrap.wrap(s, 40)
print(s_wrap_list)
# ['Python can be easy to pick up whether', "you're a first time programmer or you're", 'experienced with other languages']

得られたリストを使って'\n'.join(list)とすると改行コード\nで改行された文字列が取得できる。

print('\n'.join(s_wrap_list))
# Python can be easy to pick up whether
# you're a first time programmer or you're
# experienced with other languages

fill()関数は、リストではなく改行された文字列を返す。上の例のようにwrap()のあとで'\n'.join(list)するのと同じ。

リストが必要なく固定幅の文字列を出力したいだけならfill()のほうが便利。

print(textwrap.fill(s, 40))
# Python can be easy to pick up whether
# you're a first time programmer or you're
# experienced with other languages

wrap()fill()は同じ名前のキーワード引数を受け取る。

引数max_lineに行数を指定すると、それ以降の行は省略される。

print(textwrap.wrap(s, 40, max_lines=2))
# ['Python can be easy to pick up whether', "you're a first time programmer or [...]"]

print(textwrap.fill(s, 40, max_lines=2))
# Python can be easy to pick up whether
# you're a first time programmer or [...]

省略される場合、デフォルトでは' [...]'が最終行の末尾に出力される。引数placeholderで任意の文字列に置き換えることができる。

print(textwrap.fill(s, 40, max_lines=2, placeholder=' ~'))
# Python can be easy to pick up whether
# you're a first time programmer or ~

また、引数initial_indentで最初の行の先頭に加えられる文字列を指定できる。段落の最初に字下げしたい場合などに使う。

print(textwrap.fill(s, 40, max_lines=2, placeholder=' ~', initial_indent='  '))
#   Python can be easy to pick up whether
# you're a first time programmer or ~

注意点: 全角半角

textwrapモジュールでは文字幅ではなく文字数で処理され、半角も全角も一文字としてカウントされる。

s = 'あいうえお、かきくけこ、12345,67890, さしすせそ、abcde'

print(textwrap.fill(s, 12))
# あいうえお、かきくけこ、
# 12345,67890,
# さしすせそ、abcde

半角全角が入り交じった日本語の文章などを固定幅で折り返したい場合は、以下のページが参考になる。

文字列を切り詰め(省略): shorten()

文字列を切り詰めて省略するには、textwrapモジュールのshorten()関数を使う。

任意の文字数に収まるように単語単位で省略される。省略を示す文字列(デフォルトでは' [...]'、引数placeholderで設定可能)も含めて任意の文字数に収まる。

s = 'Python is powerful'

print(textwrap.shorten(s, 12))
# Python [...]

print(textwrap.shorten(s, 12, placeholder=' ~'))
# Python is ~

日本語の文字列の場合、単語に分割できないのでうまく省略できない。

s = 'Pythonについて。Pythonは汎用のプログラミング言語である。'

print(textwrap.shorten(s, 20))
# [...]

単語単位ではなく、文字数だけ考慮して省略するにはスライスを使えばよい。

s_short = s[:12] + '...'
print(s_short)
# Pythonについて。P...

半角、全角を考慮して文字幅をカウントしたい場合は、以下の記事を参照。

TextWrapperインスタンスの利用

決まった設定で何度もwrap()fill()を行う場合は、TextWrapperインスタンスを生成すると効率が良い。

コンストラクタにwidthmax_linesなどの引数を指定してインスタンスを生成すると、その設定でwrap()fill()メソッドを繰り返し実行できる。

tw = textwrap.TextWrapper(width=30, max_lines=3, placeholder=' ~', initial_indent='  ')

s = "Python can be easy to pick up whether you're a first time programmer or you're experienced with other languages"

print(tw.wrap(s))
# ['  Python can be easy to pick', "up whether you're a first time", "programmer or you're ~"]

print(tw.fill(s))
#   Python can be easy to pick
# up whether you're a first time
# programmer or you're ~

属性を変更することで、生成後に設定を変更することも可能。

tw.placeholder = ' ...'
tw.initial_indent = ''

print(tw.fill(s))
# Python can be easy to pick up
# whether you're a first time
# programmer or you're ...

関連カテゴリー

関連記事