LoginSignup
1
3

More than 3 years have passed since last update.

Pythonの標準ライブラリ:後半(Python学習メモ⑨)

Last updated at Posted at 2019-12-16

出力整形

reprlib, pprint, textwrap, localeなど


import reprlib
import pprint
import textwrap
import locale

# reprlibはrepr()の別バージョンで、巨大なコンテナお部ジェクトを省略して表示する
charset = reprlib.repr(set('supercalifragilisticexpialidocious'))
print(charset)
# {'a', 'c', 'd', 'e', 'f', 'g', ...}

# pprintはデータ構造を分かりやすく表示してくれる
t = [[[['black', 'cyan'], 'white', ['green', 'red']], [['magenta', 'yellow'], 'blue']]]
pprint.pprint(t, width=30)
# [[[['black', 'cyan'],
#    'white',
#    ['green', 'red']],
#   [['magenta', 'yellow'],
#    'blue']]]

# textwrap.fill()は各段落を指定の幅におさまるように折り返してくれる
doc = """The wrap() method is just like fill() except that it returns a list of strings instead of one big string with newlines to separate the wrapped lines."""
print(textwrap.fill(doc, width=40))
# The wrap() method is just like fill()
# except that it returns a list of strings
# instead of one big string with newlines
# to separate the wrapped lines.

# localeは国ごとの表現(単位など)を呼び出すことができる
locale.setlocale(locale.LC_ALL, 'English_United States.1252')
conv = locale.localeconv()
x = 1234567.8
print(locale.format("%d", x, grouping=True))
# 1,234,567
print(locale.format_string("%s%.*f", (conv['currency_symbol'], conv['frac_digits'], x), grouping=True))
# $1,234,567.80

テンプレート

ポイント

  • Templateモジュールを使うと置き換え記号($)を使ったテンプレート文字列を実装することができる
  • $の後に英数字、アンダースコアを用いた数字を続けられる
  • \$は\$でエスケープ可能
  • $のあとに{}を続けるとスペースを入れなくても英数字、アンダースコアを続けることが可能
from string import Template
t = Template('${village}folk send $$10 to $cause.')
sentence = (t.substitute(village='Nottingham', cause='the ditch func'))

print(sentence)
# Nottinghamfolk send $10 to the ditch func.


# substituteメソッドはプレースホルダをディクショナリか
# キーワード引数を渡さないとKeyErrorとなるので、
# safe_substituteメソッドの方が安全な場合がある
# データがなければプレースホルダはそのまま出力される
t = Template('Return the $item to $owner.')
d = dict(item='unladen swallow')
sentence = t.safe_substitute(d)

print(sentence)
# Return the unladen swallow to $owner.

Templateのサブクラスでは$の代わりに、区切り文字を変えることもできる

ファイル目の変更
import time, os.path
from string import Template

photofiles = ['img_1074.jpg', 'img_1076.jpg', 'img_1077.jpg']

class BatchRename(Template):
    delimiter = '%'

fmt = input('どのようにリネームしますか (%d- 日付 %n- 番号 %f- 形式): ')
# どのようにリネームしますか (%d- 日付 %n- 番号 %f- 形式): Ashley_%n%f 

t = BatchRename(fmt)
date = time.strftime('%d%b%y')

for i, filename in enumerate(photofiles):
    base, ext = os.path.splitext(filename)
    newname = t.substitute(d=date, n=i, f=ext)
    print('{0} --> {1}'.format(filename, newname))

# img_1074.jpg --> Ashley_0.jpg
# img_1076.jpg --> Ashley_1.jpg
# img_1077.jpg --> Ashley_2.jpg

バイナリデータレコードの処理

structモジュールのpack()unpack()を利用して、可変長のバイナリレコードを処理することが出来る

zipファイルの各ヘッダ情報にループをかける例

import struct

# rb: バイナリでread
with open('myfile.zip', 'rb') as f:
    data = f.read()

start = 0

for i in range(3): # 先頭から3つのファイルのヘッダを示す
    start += 14
    fields = struct.unpack('<IIIHH', data[start:start+16])
    crc32, comp_size, uncomp_size, filenamesize, extra_size = fields

    start += 16
    filename = data[start:start+filenamesize]
    start += filenamesize
    extra = data[start:start+extra_size]
    print(filename, hex(crc32), comp_size, uncomp_size)

    start += extra_size + comp_size # 次のヘッダまでスキップ

マルチスレッド

ポイント

  • threadingモジュールを利用することで、メインプログラムを走らせたままバックグラウンド処理ができる
import threading, zipfile

class AsyncZip(threading.Thread):
    def __init__(self, infile, outfile):
        threading.Thread.__init__(self)
        self.infile = infile
        self.outfile = outfile
    def run(self):
        f = zipfile.ZipFile(self.outfile, 'w', zipfile.ZIP_DEFLATED)
        f.write(self.infile)
        f.close()
        print('Finished background zip of:', self.infile)

background = AsyncZip('mydata.txt', 'myarchive.zip')
background.start()
print('メインプログラムは実行中です')

background.join() # バックグラウンドタスクの終了を待つ

print('メインプログラムはバックグラウンド処理の終了まで待っていました')
  • マルチスレッドアプリケーションにおけるタスク協調においては単一のメインスレッドにリソースへのアクセスを集中させておいて、ほかのスレッドからのリクエストはqueueモジュールを使ってメインスレッドに食わせる、というアプローチがよい
  • スレッド間通信にはQueueオブジェクトを使うと設計しやすく可読性も上がる

ログ取り

ポイント

  • loggingモジュールでは柔軟なログ記録システム
  • デフォルトではDEBUGメッセージとINFOメッセージが抑制されている
  • デフォルトでは出力先は標準エラー出力になっている
  • 出力オプションとしてはほかにeメール、データグラム、ソケット、HTTPサーバへの転送がある
  • メッセージの優先度毎に出力先を選ぶこともできる
import logging

logging.debug('Debugging information')
logging.info('Informational message')
logging.warning('Warning: config file %s not found', 'server.conf')
logging.error('Error occurred')
logging.critical('Critical error -- shutting down')

# WARNING:root:Warning: config file server.conf not found
# ERROR:root:Error occurred
# CRITICAL:root:Critical error -- shutting down

弱参照

  • weakrefを用いると参照を生成せずにオブジェクトを追跡することができる
  • 不要になったオブジェクトは自動的に弱参照表から除かれ、弱参照オブジェクトへのコールバックが起きる
import weakref, gc

class A:
    def __init__(self, value):
        self.value = value
    def __repr__(self):
        return str(self.value)

a = A(10) # 参照を生成する
d = weakref.WeakValueDictionary()
d['primary'] = a # 参照を生成しない
print(d['primary']) # オブジェクトが生きていれば取ってくる
10

del a # 参照を削除
gc.collect() # ガベージコレクションを実行

d['primary'] # エントリは自動的に削除されている
# Traceback (most recent call last):
#   File ".\weakref_sample.py", line 17, in <module>
#     d['primary'] # エントリは自動的に削除されている
#   File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.7_3.7.1520.0_x64__qbz5n2kfra8p0\lib\weakref.py", line 137, in __getitem__      
#     o = self.data[key]()
# KeyError: 'primary'

リスト操作のツール

  • arrayモジュールは、同室のデータのみを収めるリスト類似のオブジェクトarrayを提供する

from array import array

a = array('H', [4000, 10, 700, 22222])
print(sum(a))
# 26932

print(a[1:3])
# array('H', [10, 700])
  • collectionsモジュールは左端部へのappendpopはリストより高速だが、中央部の参照は低速であるdequeオブジェクトをもたらす
  • キューや幅優先ツリー検索を実装するときに便利

from collections import deque
d = deque(["task1", "task2", "task3"])
d.append("task4")
print("Handling", d.popleft())

unsearched = deque([starting_node])
def breadth_first_search(unsearched):
    node = unsearched.popleft()
    for m in gen_moves(node):
        if is_goal(m):
            return m
        unsearched.append(m)
  • ソート済みリストを操作する関数を持つbisectモジュールなども備えている
  • heapqモジュールは通常のリストをベースにヒープを実装する関数を提供する

10進数の浮動小数点計算

  • decimalモジュールは浮動小数点10進数で計算するためのデータ型Decimalを提供する
  • float型より厳密な計算が可能
1
3
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
1
3