2017/04/26

Python Tips: GetText (.po) ファイルの要素を抽出したい

Python で、 GetText (.po) ファイルの要素を抽出する方法をご紹介します。

「 GetText って何?」という方は Wikipedia を参考になさってみてください。

- gettext - Wikipedia

pip パッケージのひとつに polib というものがあり、こちらを使うと GetText (.po) ファイル(以下 .po ファイル)を Python でシンプル・かんたんに扱うことができます。


インストール


インストールにはおなじみ pip コマンドを使用しましょう。

pip install polib


使い方


.po ファイルの読み込みには pofile() 関数を使います。

import polib

po = polib.pofile('path/to/catalog.po')

作成日や作成者を含むメタデータは metadata プロパティに格納されています。

print(po.metadata)

.po ファイルに含まれる各翻訳テキストは POFile オブジェクトをイテレータとして使用すると取得することができます。

for entry in po:
    print('{}: {}'.format(entry.msgid, entry.msgstr))

有効な翻訳文を持つ翻訳テキストのみに限定して取得したい場合は translated_entries() メソッドが便利です。

for entry in po.translated_entries():
    print('{}: {}'.format(entry.msgid, entry.msgstr))

以上です。

ここでご紹介したのは .po ファイルの要素を抽出する方法だけですが、 polib では他にも「要素の追加」「 .po ファイルの新規作成」「 .po ファイルの更新」などひととおりの処理がサポートされています。興味のある方は公式の Quick start guide をご覧になってみてください。

Quick start guide — polib documentation

私の場合は「巨大な .po ファイルのうち一部の要素を切り出して小さな .po ファイルを作りたい」という要望があり、 .po ファイルからの要素抽出スクリプトを作成するのに使用しました。興味のある方は次の gist の方も参考にしてみてください。



参考

- polib : Python Package Index
- Welcome to polib’s documentation! — polib documentation

2017/04/02

Python Tips:特定のサイズ以上のファイルを検索したい

バタバタしており久しぶりの投稿になってしまいました。

今回は Python で指定されたサイズ以上のファイルを検索する方法をご紹介します。

これを実現するアプローチとしてはいくつかの方法が考えられるかと思いますが、今回は標準ライブラリの pathlib を使った方法をご紹介してみたいと思います。

from pathlib import Path

pathlib の Path クラスを使えば OOP スタイルで OS のファイルシステムを操作することができます。

Path クラスの数あるメソッドのうち次の 4 つほどをおさえておけば、ファイルを探す処理の実装には十分でしょう。

- iterdir() ディレクトリの中にあるファイル / ディレクトリを全件返す
- is_dir() ディレクトリかどうかをチェックする
- is_file() ファイルかどうかをチェックする
- stat() ファイルサイズを含むファイルのメタ情報を返す

サンプルコードを書いてみます。

# coding: utf-8
from pathlib import Path

def search_files(path, size_min_in_byte):
    """指定されたパスの下にある指定されたサイズ以上のファイル名を一覧表示する
    """
    size_min_in_mb = size_min_in_byte << 20

    p = Path(path)

    # 指定されたパス以下のファイルを再帰的にチェックする
    # 指定されたサイズ以上のファイルは「 10MB  ファイル名」といった感じに表示する
    for file in p.iterdir():
        if file.is_dir():
            search_files(file, size_min_in_byte)
        elif file.is_file():
            size = file.stat().st_size
            if size >= size_min_in_mb:
                # resolve() を使って絶対パスを表示する
                print('{:.1f}MB\t{}'.format(size >> 20, file.resolve()))


if __name__ == '__main__':
    # hayato のデスクトップ以下にあるサイズが 1MB 以上のファイルを表示する
    path = '/Users/hayato/Desktop'
    size_in_mb = 2
    search_files(path, size_in_mb)


ファイル名を script_name.py として保存しターミナルで実行してみましょう。私の環境では例えば次のような出力が出ます。

$ python script_name.py
3.5MB /Users/hayato/Desktop/山月記.md
2.2MB /Users/hayato/Desktop/弟子.md
2.7MB /Users/hayato/Desktop/李陵.md

これはちょうど、 find コマンドでファイルサイズを指定した場合と同じような結果になります。

find /Users/hayato/Desktop -type f -size +2M

ここでは単純にサイズとファイル名を標準出力に返していますが、対象のファイルそれぞれに対して特定の処理を行いたい場合などは print 文の前後を必要な処理に差し替えるとよいものと思います。

以上です。

例えば、コマンドライン引数をかんたんに扱うための標準ライブラリ argparse といっしょに使うともう少し汎用性の高いスクリプトを作ることができます。興味のある方は次のスニペットもよろしければ参考にしてみてください。