ラベル 外部ライブラリ の投稿を表示しています。 すべての投稿を表示
ラベル 外部ライブラリ の投稿を表示しています。 すべての投稿を表示

2020年7月19日

続・TOMLを使ってみよう

以前 こちらの記事 で、データ記述言語 TOML と、TOML に関する Python の状況について述べました。
この記事より数年が経ち、現在どのような状況になっているかについて、改めて述べたいと思います。


まず、TOML の変化ですが、

  • Version 1.0 が出た
  • リストに複数の型を含めることができるようになった
となります。

前回の記事 時点ではまだ Version 0.4 でしたが、無事に正式版 1.0 がリリースされています。
また、リストに1つの型しか適用できないという仕様は、データを格納する目的で TOML を使用する際の大きな足かせになることが考えられましたが、Version 1.0 への更新過程で撤廃されました。

この2点を考えると、TOML は十分実用可能段階であり、JSON からの置き換えを積極的に進められる状態にあると言えます。


続いて Python 側の変化ですが、

  • pip でインストールできる toml モジュールがある
となります。

前回の記事 当時は、1ファイルからなるモジュールを入手可能でしたが、細かなバグがあちこちにあり、実使用には少々難がありました。現在の toml モジュールを試したところ、私が気づいてたバグは全て修正されていました。

Python 側の TOML への対応も十分準備ができていると言えます。


あとは、toml モジュールが標準へ昇格すれば、いよいよ大手を振って TOML の時代が来たと言えることになります。

2019年4月25日

pyflakes と flake8 の紹介

以前にソースコードの静的解析を行う pylint を紹介しました。
今回は、同じくソースコードの静的解析を行う pyflakes を紹介します。


pylint の記事と同じ以下のソースコードに対して、pyflakes を走らせます。
def make_plural(fruit):
    if fruit == 'apple':
        plural = 'apples'
    elif fruit == 'orange':
        plural = 'oranges'
    elif fruits == 'peach':
        plural = 'peaches'
    else:
        prural = ''

    return plural
結果は以下のようになりました。
fruit.py:6: undefined name 'fruits'
fruit.py:9: local variable 'prural' is assigned to but never used
pylint と同じく2箇所のバグを指定してくれています。lint として十分使えるのではないかと思われます。


ここまで、pyflakes について簡単に紹介してきました。しかし、実際には pyflakes を単品で使うことは少なくて、より統合化された flake8 を使うのが一般的です。
flake8 はデフォルトでは pyflakes + pycodestyle としてチェックを行います。つまり、ソースコードの解析は pyflakes が、ソースコードのスタイルチェックは pycodestyle が行い、結果はまとめて表示されます。pyflakes と pycodestyle を別々に走らせる必要がないわけで、単純に便利ですよね。

さらに、flake8 はプラグインを導入することで、別のチェックを追加することができるようになっています。
最も有名なのは、pydocstyle を追加する flake8-docstrings でしょうか。このプラグインをインストールすると、pyflakes + pycodestyle + pydocstyle の3つのチェックを一度で行えることになります。
他にも、様々なプラグインが公開されています。

2019年4月21日

pep8 と pep257 の名前変更

以前に当ブログでも紹介した pep8 の名前が、pycodestyle に変更となりました。

Guido氏自らが「"PEP8"と言ったときに、ドキュメントの"PEP8"なのか、プログラムの"pep8"なのか、分からないのは良くない」と提議したことによります。
https://github.com/PyCQA/pycodestyle/issues/466
なお、提議の最後は、「"pep8"は素晴らしく、私も使っている。これを作らせた人も素晴らしい(※自身のこと)」とジョークを混じえ、提議の対象が名称だけであることを強調しています。

この提議の結果、pep8 は pycodestyle に名称が変更されました。
ただし、当面の互換性のため、pep8 はそのまま残り、pycodestyle というモジュールが新たに作られるという形になりました。pep8 は更新停止、今後のバージョンアップは pycodestyle のみで行われる、ということになります。


pep8 と同じ理由から、pydoc用の文字列をチェックする pep257 も、pydocstyle に変更されました。当面 pep257 は残る点、pep257 の更新が停止した点も、pep8 と同じです。

2016年2月22日

PILが対応しているフォーマット一覧

PIL は多くの画像フォーマットに対応しています。
本項では、PILが対応しているフォーマットの調べ方を紹介します。


以下のソースコードで、PILが対応しているフォーマットの一覧が出力されます。
protected属性のアトリビュートにアクセスしているので、あまり良いソースコードではないですが、知っておいて損はないと思います。

import PIL.Image

for plugin in PIL.Image._plugins:
    __import__('PIL.' + plugin)

print(PIL.Image.ID)

2016年2月15日

画像ライブラリPIL

Python にて画像を扱うライブラリ PIL を紹介します。

PIL は標準ライブラリには含まれていませんが、Python において画像処理と言えばまず PIL の名が挙げられるほどに有名なライブラリです。
なお、元祖PIL は Python 3 に対応しておらず、有志により引き継がれた Pillow が Python 3 用のライブラリとなっています。Python 3 でも、旧名である PIL と呼ばれることの方が多いです。


以下に画像整理向けの4つの使い方を紹介します。
どれも直感的で分かりやすいインターフェースになっていることが見て取れるかと思います。


1)画像を切り抜く
crop() 関数を使うことで、画像を切り抜くことができます。
デスクトップのスクリーンショットから所定のウィンドウを切り抜く場合などに使えると思います。

import PIL.Image
import glob

dir_name = 'screenshot/'

for png in glob.glob(dir_name + '*.png'):
    # 画像を開く
    src = PIL.Image.open(png)

    # crop()で切り抜き
    dst = src.crop((0, 0, 250, 400))

    # 切り抜かれた画像を保存
    dst.save(png)

2)画像を小さくする
resize() 関数を使うことで、画像のサイズを変更できます。画質を保つために、resize() の第二引数として PIL.Image.ANTIALIAS を指定するのが一般的です。
デジカメ画像を小さくする場合などに使えると思います。
import PIL.Image
import glob

dir_name = 'photo/'

for jpg in glob.glob(dir_name + '*.jpg'):
    # 画像を開く
    src = PIL.Image.open(jpg)

    # resize()でサイズ変更
    dst = src.resize((800, 600), PIL.Image.ANTIALIAS)

    # サイズ変更された画像を保存
    dst.save(jpg)

3)JPEG のクオリティを落とす
JPEG ファイルは保存時にクオリティを指定できます。オリジナルの画像のクオリティが高すぎて容量が気になる場合には、クオリティを落とすのも一つの手です。ちなみに、PIL のデフォルト値は 75 です。
import PIL.Image
import glob

dir_name = 'photo/'

for jpg in glob.glob(dir_name + '*.jpg'):
    # 画像を開く
    src = PIL.Image.open(jpg)

    # save()にquality引数を与える
    src.save(jpg, quality=60, optimize=True, progressive=True)

4)画像フォーマットを変換する
save() 関数の第二引数で画像フォーマットを指定できます。
import PIL.Image
import glob

dir_name = 'img/'

for bmp in glob.glob(dir_name + '*.bmp'):
    # 画像を開く
    src = PIL.Image.open(bmp)

    # ファイル名を'*.bmp' → '*.png'
    png = '.png'.join(bmp.rsplit('.bmp', 1))

    # PNGとして保存
    src.save(png, 'PNG')

2016年1月25日

ゴミ箱への移動は Send2Trash

ファイルをゴミ箱に入れるためのライブラリ send2trash を紹介します。

ファイルを削除する時、純粋なファイルの削除ではなく、ゴミ箱への移動をさせたい場合があります。しかし残念ながら、Pythonの標準はゴミ箱への移動をサポートしていません(os.remove() はファイルを完全に削除します)。
そこで本項で紹介する send2trash の出番です。

send2trash はプラットフォームに応じたゴミ箱への移動の処理を行ってくれます。使う側がすることは、関数を呼ぶだけ。素晴らしくシンプルですね。

>>> from send2trash import send2trash

>>> send2trash('file_name')

2015年12月20日

pep8でスタイルチェック

Python ソースコードのコーディングスタイルをチェックする pep8 を紹介します。

pep8 はその名の通り、ソースコードが PEP8 に準拠しているかどうかをチェックするライブラリです。
以下のソースコードを pep8 でチェックしてみます。

__version__ = '1.0.0'

import fnmatch
import os

def my_glob(root_dir='.', pattern='*', recursive=False):
    paths = []
    append = paths.append
    
    for loop_dir, _, files in os.walk(root_dir, topdown=True): # topdown shall be True
        for file in files:
            if fnmatch.fnmatch(file, pattern):
                append(os.path.join(loop_dir, file))

        if not recursive:  # if not recursive, break in first loop
            break

    return  paths

チェック結果は以下のようになりました。ソースコードの書式について、いくつか指摘が挙がっています。
3: E402 module level import not at top of file
4: E402 module level import not at top of file
6: E302 expected 2 blank lines, found 1
9: W293 blank line contains whitespace
10: E261 at least two spaces before inline comment
10: E501 line too long (86 > 79 characters)
18: E271 multiple spaces after keyword

(対訳)
3行目: E402 importは最上部に書くべき
4行目: E402 importは最上部に書くべき
6行目: E302 関数の前は2行空けるべき、1行しか空いていない
9行目: W293 空行に空白が混じっている
10行目: E261 文中のコメントは、# の前に空白を2つ以上置くべき
10行目: E501 行の文字数が多すぎる (86文字 > 79文字)
18行目: E271 returnの後ろにスペースが複数ある

pep8 の特徴として以下が挙げられます。
  • 動作が軽量
  • 指摘理由が PEP8 由来であるという点がハッキリしている
  • あくまでコーディングスタイルのチェックであり、ソースコードの分析は行わない
ソースコードはプログラマーの成果物です。世に出す前には、このツールで形を整えておきたいところです。

2015年12月16日

Excelの読み込み/書き込み

Python から Excel ファイルを読み込み/書き込みする方法を紹介します。

Python から Excel ファイルを操作するためのライブラリは幾つかあります。その中で、Excel ファイル読み込み用のライブラリ xlrd と、書き込み用のライブラリ xlwt が最も広く知られているようです。(両ライブラリを組み合わせ使う xlutils というライブラリもあるのですが、こちらは残念ながら Python 3 には未対応です)。
詳しい使い方はこちらのサイトが参考になります。と言うか、非常にうまくまとめておられるので、当ページで使い方を再紹介する必要は無いと感じました。


ところで、オープンソースである Python と、Microsoft社の製品である Excel は、根本思想の部分で異なる点が多いです。それでもなお、Python で Excel をサポートすべき理由は何でしょうか?
私が実際に経験したのですが、とあるツールの設定データを Excel ファイルから読み込めるようにすると、非プログラマの方々から好評を得ました。
その時の Excel の書式は以下のようなものでした。

[設定ファイルとしてのExcel]

[各項目の詳細をコメントで記載]


プログラマ的には、この程度の設定データならばテキストファイルで書くのが近道のように思います。
しかし、「文字列は " で括る」「# で始まる行はコメント」というようなルールは、非プログラマにとっては馴染みのないものです。
GUIを作るほどでもなく、それでも非プログラマにも使いやすいようにしたい時、Excel を使うというのは一つの答えであると思います。

2015年12月8日

TOMLを使ってみよう

TOML は Tom's Obvious, Minimal Language の略で、データ記述言語の一つです。
XML、YAML、JSON といった言語からの置き換えを狙って提唱された言語のようで、未だ正式版(v1.0.0)は発行されていませんが、今後普及していくのではないかと予想されます。ちなみに提唱者である Tom氏は GitHub の創設者です。
(以下の記事内容は執筆時点の最新版である v0.4.0 に基づきます。)


TOML の公式ページはこちらです(当然、GitHub です)。
TOML の長所は以下のようになります。

  • 仕様はかなりシンプル
  • テキストベースでヒューマンリーダブル
  • 設定ファイルに特化した記法をサポート
  • コメントを書ける、UTCがプリミティブ型、複数行の文字列を書ける、配列で末尾の , が許される、など細かい配慮が行き届いている


以下は公式ページにあるサンプルデータの抜粋です。[] を利用する INIファイルに似た書式をサポートしている点が、最大の特徴と思われます。
# This is a TOML document.

title = "TOML Example"

[owner]
name = "Tom Preston-Werner"
dob = 1979-05-27T07:32:00-08:00 # First class dates

[database]
server = "192.168.1.1"
ports = [ 8001, 8001, 8002 ]
connection_max = 5000
enabled = true

[servers]

  # Indentation (tabs and/or spaces) is allowed but not required
  [servers.alpha]
  ip = "10.0.0.1"
  dc = "eqdc10"

  [servers.beta]
  ip = "10.0.0.2"
  dc = "eqdc10"

[clients]
data = [ ["gamma", "delta"], [1, 2] ]

# Line breaks are OK when inside arrays
hosts = [
  "alpha",
  "omega"
]

TOML のライブラリは未だ Python の標準ライブラリには含まれていません。
TOML の公式ページがからリンクされているこちらのライブラリを使って、TOML データの読み込みを行ってみます。
>>> import toml

>>> toml.load(open('sample.toml'))
{
    'servers': {
        'alpha': {'dc': 'eqdc10', 'ip': '10.0.0.1'},
        'beta': {'dc': 'eqdc10', 'ip': '10.0.0.2'}
    },
    'database': {
        'enabled': True,
        'connection_max': 5000,
        'ports': [8001, 8001, 8002],
        'server': '192.168.1.1'
    },
    'title': 'TOML Example',
    'clients': {
        'data': [['gamma', 'delta'], [1, 2]],
        'hosts': ['alpha', 'omega']
    },
    'owner': {
        'dob': datetime.datetime(1979, 5, 27, 7, 32),
        'name': 'Tom Preston-Werner'
    }
}
極簡単に TOML のデータを読み込むことができました。


ここまで、TOML の長所とサンプルについて見てきました。シンプルかつ強力なデータ記述言語であると言えます。

しかし、現時点で TOML を本格的に使うにあたって、以下の2つの問題点があります。

  • Python を含め、多くの言語が標準では未対応
  • 配列の要素は同じ型でなければならない
1点目は今後改定・普及することで解消するのではないかと思われます。
一方、2点目は Python のデータを記述する際に大きな制限となってしまいます。v1.0.0 までにこの点が解消しなければ、「設定ファイルとして利用する」以外の使い道を見つけにくくなってしまうのではないかと危惧されます。

2015年12月4日

pylintは是非使おう

Python ソースコードの静的解析を行う pylint を紹介します。
pylint は Python での lint の代表的な実装です。外部ライブラリであり、インストールも少々大掛かりですが、lint としての機能は十分に高いです。



以下のようなソースコードを考えます。

def make_plural(fruit):
    if fruit == 'apple':
        plural = 'apples'
    elif fruit == 'orange':
        plural = 'oranges'
    elif fruits == 'peach':
        plural = 'peaches'
    else:
        prural = ''

    return plural
この11行の中に、タイプミスによるバグが2つあります。
C言語や Java のような静的言語であれば、このようなタイプミスはコンパイル時に見つかります。しかし、Python をはじめとする動的言語では、実行してその箇所を通った時に、初めてエラーとして表に出ます。
静的言語と動的言語の比較は簡単な問題ではありませんが、動的言語を書く場合には、このようなタイプミスが起こらないようにテストやレビューをしっかり行うことは必須となります。


では、上記のソースコードを pylint で解析してみます。

[E0602(undefined-variable), main] Undefined variable 'fruits'
[W0612(unused-variable), main] Unused variable 'prural'
2つのタイプミスが解析結果で指摘されています。
これらの指摘は、プログラム解析を行った結果として得られたものです。即ち、コードの形だけをチェックしたのではなく、中身まで分析した結果として指摘が得られています。この点は pylint の大きな強みです。

もちろん pylint の指摘が常に正しいとは限りません。また、少々口うるさく感じられる場面もあります。
それでも、ここで例に挙げたようなタイプミスによるバグを防ぐためにも、ソースコードを世に出す前には pylint で静的解析をしておくことは必須と言えます。

2015年11月7日

Benchmarker.py

ベンチマークツール「Benchmarker.py」を紹介します。

公式ページからの抜粋によると、"Benchmarker.py is an awesome benchmarking tool for Python."とのことですが、使っているとまさにそのように感じます。



実際の使用例として、公式ページで説明されているサンプルに若干手を加えたソースを走らせてみます。

from benchmarker import Benchmarker

with Benchmarker(1000 * 1000, width=20) as bench:
    s1, s2, s3, s4, s5 = (
        'Haruhi', 'Mikuru', 'Yuki', 'Itsuki', 'Kyon'
    )

    @bench('join')
    def _(bm):
        for _ in bm:
            s = ''.join((s1, s2, s3, s4, s5))

    @bench('+ operator')
    def _(bm):
        for _ in bm:
            s = s1 + s2 + s3 + s4 + s5

    @bench('% operator')
    def _(bm):
        fmt = '%s%s%s%s%s'
        for _ in bm:
            s = fmt % (s1, s2, s3, s4, s5)

    @bench('format')
    def _(bm):
        fmt = '{0}{1}{2}{3}{4}'
        for _ in bm:
            s = fmt.format(s1, s2, s3, s4, s5)

以下のような結果が表示されます(一部抜粋)。
''.join()が高速であるというよく知られた事実を確認することが出来ました。
## benchmarker:         release 4.0.1 (for python)
## python version:      3.4.0
## python compiler:     MSC v.1600 32 bit (Intel)
## python platform:     Windows-8-6.2.9200
...

## Ranking                real
join                    1.1875  (100.0) ********************
+ operator              1.6094  ( 73.8) ***************
% operator              2.0491  ( 58.0) ************
format                  3.5278  ( 33.7) *******
...


私が感じた Benchmarker.py の長所について列挙します。
  • 計測用のソースコードが書きやすい
  • 出力結果が見やすい
  • 計測方法の細かなチューニングが可能(ここでは使っていませんが)
  • 簡単に使用する分には、大半のオプションは未使用のままでもOK


本ブログではベンチマークの測定に、この Benchmarker.py を使っていきます。