본문 바로가기

python tutorial -11 표준 라이브러리 2

https://docs.python.org/ko/3/tutorial/stdlib2.html

python tutorial part 11 

표준 라이브러리 2


11.1. 출력 포매팅 出力のフォーマット


reprlib 모듈은 크거나 깊게 중첩된 컨테이너의 축약 된 디스플레이를 위해 커스터마이즈된 repr() 의 버전을 제공합니다:

reprlib モジュールは、大きなコンテナや、深くネストしたコンテナを省略して表示するバージョンの repr() を提供しています:

>>>
>>> import reprlib
>>> reprlib.repr(set('supercalifragilisticexpialidocious'))
"{'a', 'c', 'd', 'e', 'f', 'g', ...}"


pprint 모듈은 인터프리터가 읽을 수 있는 방식으로 내장 객체나 사용자 정의 객체를 인쇄하는 것을 보다 정교하게 제어할 수 있게 합니다. 결과가 한 줄보다 길면 "예쁜 프린터"가 줄 바꿈과 들여쓰기를 추가하여 데이터 구조를 보다 명확하게 나타냅니다:

pprint モジュールは、組み込み型やユーザ定義型をわかりやすく表示するための洗練された制御手段を提供しています。表示結果が複数行にわたる場合は、 "pretty printer" と呼ばれるものが改行やインデントを追加して、データ構造がより明確になるように印字します:

>>>
>>> import pprint
>>> t = [[[['black', 'cyan'], 'white', ['green', 'red']], [['magenta',
...     'yellow'], 'blue']]]
...
>>> pprint.pprint(t, width=30)
[[[['black', 'cyan'],
   'white',
   ['green', 'red']],
  [['magenta', 'yellow'],
   'blue']]]


textwrap 모듈은 텍스트의 문단을 주어진 화면 너비에 맞게 포맷합니다:

textwrap モジュールは、段落で構成された文章を、指定したスクリーン幅にぴったり収まるように調整します:

>>>
>>> import textwrap
>>> 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의 format 함수의 grouping 어트리뷰트는 그룹 구분 기호로 숫자를 포매팅하는 직접적인 방법을 제공합니다:

locale モジュールは、文化により異なるデータ表現形式のデータベースにアクセスします。 locale の format() 関数の grouping 属性を使えば、数値を適切な桁区切り文字によりグループ化された形式に変換できます:

>>>
>>> import locale
>>> locale.setlocale(locale.LC_ALL, 'English_United States.1252')
'English_United States.1252'
>>> conv = locale.localeconv()          # get a mapping of conventions
>>> x = 1234567.8
>>> locale.format("%d", x, grouping=True)
'1,234,567'
>>> locale.format_string("%s%.*f", (conv['currency_symbol'],
...                      conv['frac_digits'], x), grouping=True)
'$1,234,567.80'


11.2. 템플릿 文字列テンプレート

string 모듈은 다재다능한 Template 클래스를 포함하고 있는데, 최종 사용자가 편집하기에 적절한 단순한 문법을 갖고 있습니다. 따라서 사용자는 응용 프로그램을 변경하지 않고도 응용 프로그램을 커스터마이즈할 수 있습니다.

string モジュールには、柔軟で、エンドユーザが簡単に編集できる簡単な構文を備えた Template クラスが入っています。このクラスを使うと、ユーザがアプリケーションを修正することなしにアプリケーションの出力をカスタマイズできるようになります。


형식은 $ 와 유효한 파이썬 식별자 (영숫자와 밑줄)로 만들어진 자리표시자 이름을 사용합니다. 중괄호를 사용하여 자리표시자를 둘러싸면 공백없이 영숫자가 뒤따르도록 할 수 있습니다. $$을 쓰면 하나의 이스케이프 된 $ 를 만듭니다:

テンプレートでは、$ と有効な Python 識別子名 (英数字とアンダースコア) からなるプレースホルダ名を使います。プレースホルダの周りを {} で囲えば、プレースホルダの後ろにスペースを挟まず、英数文字を続けることができます。$$ のようにすると、$ 自体をエスケープできます:

>>>
>>> from string import Template
>>> t = Template('${village}folk send $$10 to $cause.')
>>> t.substitute(village='Nottingham', cause='the ditch fund')
'Nottinghamfolk send $10 to the ditch fund.'


substitute() 메서드는 자리표시자가 딕셔너리나 키워드 인자로 제공되지 않을 때 KeyError 를 일으킵니다. 메일 병합 스타일 응용 프로그램의 경우 사용자가 제공한 데이터가 불완전할 수 있으며 safe_substitute() 메서드가 더 적절할 수 있습니다. 데이터가 누락 된 경우 자리표시자를 변경하지 않습니다:


substitute() メソッドは、プレースホルダに相当する値が辞書やキーワード引数にない場合に KeyError を送出します。メールマージ機能のようなアプリケーションの場合、ユーザが入力するデータは不完全なことがあるので、欠落したデータがあるとプレースホルダをそのままにして出力する safe_substitute() メソッドを使う方が適切かもしれません:

>>>
>>> t = Template('Return the $item to $owner.')
>>> d = dict(item='unladen swallow')
>>> t.substitute(d)
Traceback (most recent call last):
  ...
KeyError: 'owner'
>>> t.safe_substitute(d)
'Return the unladen swallow to $owner.'


Template 서브 클래스는 사용자 정의 구분자를 지정할 수 있습니다. 예를 들어 사진 브라우저를 위한 일괄 이름 바꾸기 유틸리티는 현재 날짜, 이미지 시퀀스 번호 또는 파일 형식과 같은 자리표시자에 백분율 기호를 사용하도록 선택할 수 있습니다:

区切り文字はデフォルトは $ ですが、Template のサブクラスを派生すると変更することができます。例えば、画像ブラウザ用に一括で名前を変更するユーティリティを作っていたとして、現在の日付や画像のシーケンス番号、ファイル形式といったプレースホルダにパーセント記号を使うことにしたら、次のようになります:

>>>
>>> import time, os.path
>>> photofiles = ['img_1074.jpg', 'img_1076.jpg', 'img_1077.jpg']
>>> class BatchRename(Template):
...     delimiter = '%'
>>> fmt = input('Enter rename style (%d-date %n-seqnum %f-format):  ')
Enter rename style (%d-date %n-seqnum %f-format):  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


템플릿의 또 다른 응용은 다중 출력 형식의 세부 사항에서 프로그램 논리를 분리하는 것입니다. 이렇게 하면 XML 파일, 일반 텍스트 보고서 및 HTML 웹 보고서에 대한 커스텀 템플릿을 치환할 수 있습니다.

テンプレートのもう一つの用途は、複数ある出力フォーマットからのプログラムロジックの分離です。これにより、XMLファイル用、プレーンテキストのレポート用、HTMLのwebレポート用のテンプレートに、同じプログラムロジックから値を埋め込むことができます。


11.3. 바이너리 데이터 레코드 배치 작업  バイナリデータレコードの操作


struct 모듈은 가변 길이 바이너리 레코드 형식으로 작업하기 위한 pack() 과 unpack() 함수를 제공합니다. 다음 예제는 zipfile 모듈을 사용하지 않고 ZIP 파일의 헤더 정보를 루핑하는 법을 보여줍니다. 팩 코드 "H" 와 "I" 는 각각 2바이트와 4바이트의 부호 없는 숫자를 나타냅니다. "<" 는 표준 크기이면서 리틀 엔디안 바이트 순서를 가짐을 나타냅니다:


struct モジュールでは、様々な長さのバイナリレコード形式を操作する pack() や unpack()といった関数を提供しています。 以下の例では、 zipfile モジュールを使わずに、ZIP ファイルのヘッダ情報を巡回する方法を示しています。"H" と "I" というパック符号は、それぞれ2バイトと4バイトの符号無し 整数を表しています。 "<" は、そのパック符号が standard サイズであり、バイトオーダーがリトルエンディアンであることを示しています:

import struct

with open('myfile.zip', 'rb') as f:
    data = f.read()

start = 0
for i in range(3):                      # show the first 3 file headers
    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     # skip to the next header


11.4. 다중 스레딩 マルチスレッディング


스레딩은 차례로 종속되지 않는 작업을 분리하는 기술입니다. 스레드는 다른 작업이 백그라운드에서 실행되는 동안 사용자 입력을 받는 응용 프로그램의 응답을 향상하는 데 사용할 수 있습니다. 관련된 사용 사례는 다른 스레드의 계산과 병렬로 I/O를 실행하는 경우입니다.

スレッド処理 (threading) とは、順序的な依存関係にない複数のタスクを分割するテクニックです。スレッドは、ユーザの入力を受け付けつつ、背後で別のタスクを動かすようなアプリケーションの応答性を高めます。同じような使用例として、I/O を別のスレッドの計算処理と並列して動作させるというものがあります。


다음 코드는 메인 프로그램이 계속 실행되는 동안 고수준 threading 모듈이 백그라운드에서 작업을 어떻게 수행할 수 있는지 보여줍니다:

以下のコードでは、高水準のモジュール 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('The main program continues to run in foreground.')

background.join()    # Wait for the background task to finish
print('Main program waited until background was done.')


다중 스레드 응용 프로그램의 가장 큰 문제점은 데이터 또는 다른 자원을 공유하는 스레드를 조정하는 것입니다. 이를 위해 threading 모듈은 록, 이벤트, 조건 변수 및 세마포어를 비롯한 많은 수의 동기화 기본 요소를 제공합니다.

マルチスレッドアプリケーションを作る上で最も難しい問題は、データやリソースを共有するスレッド間の調整 (coordination)です。この問題を解決するため、threading モジュールではロックやイベント、状態変数、セマフォといった数々の同期プリミティブを提供しています。


이러한 도구는 강력하지만, 사소한 설계 오류로 인해 재현하기 어려운 문제가 발생할 수 있습니다. 따라서, 작업 조정에 대한 선호되는 접근 방식은 자원에 대한 모든 액세스를 단일 스레드에 집중시킨 다음 queue 모듈을 사용하여 해당 스레드에 다른 스레드의 요청을 제공하는 것입니다. 스레드 간 통신 및 조정을 위한 Queue 객체를 사용하는 응용 프로그램은 설계하기 쉽고, 읽기 쉽고, 신뢰성이 높습니다.

こうしたツールは強力な一方、ちょっとした設計上の欠陥で再現困難な問題を引き起こすことがあります。したがって、タスク間調整では queue モジュールを使って他の複数のスレッドからのリクエストを一つのスレッドに送り込み、一つのリソースへのアクセスをできるだけ一つのスレッドに集中させるほうが良いでしょう。スレッド間の通信や調整に Queue オブジェクトを使うと、設計が容易になり、可読性が高まり、信頼性が増します。


11.5. 로깅 ログ記録

logging 모듈은 완전한 기능을 갖춘 유연한 로깅 시스템을 제공합니다. 가장 단순한 경우, 로그 메시지는 파일이나 sys.stderr 로 보내집니다:


logging モジュールでは、数多くの機能をそなえた柔軟性のあるログ記録システムを提供しています。最も簡単な使い方では、ログメッセージをファイルや sys.stderr に送信します:

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


기본적으로 정보 및 디버깅 메시지는 표시되지 않고 출력은 표준 에러로 보내집니다. 

다른 출력 옵션에는 전자 메일, 데이터 그램, 소켓 또는 HTTP 서버를 통한 메시지 라우팅이 포함됩니다. 

새로운 필터는 메시지 우선순위에 따라 다른 라우팅을 선택할 수 있습니다: DEBUGINFOWARNINGERROR , 그리고 CRITICAL.


デフォルトでは、info() と debug() による出力は抑制され、出力は標準エラーに送信されます。選択可能な送信先には、email、データグラム、ソケット、HTTP サーバへの送信などがあります。新たにフィルタを作成すると、DEBUGINFOWARNINGERRORCRITICAL といったメッセージのプライオリティによって異なる送信先を選択することができます。


로깅 시스템은 파이썬에서 직접 구성하거나, 응용 프로그램을 변경하지 않고 사용자 정의 로깅을 위해 사용자가 편집할 수 있는 설정 파일에서 로드 할 수 있습니다.


ログ記録システムは Python から直接設定することもできますし、アプリケーションを変更しなくてもカスタマイズできるよう、ユーザが編集可能な設定ファイルによって設定することもできます。


11.6. 약한 참조 弱参照


파이썬은 자동 메모리 관리 (대부분 객체에 대한 참조 횟수 추적 및 순환을 제거하기 위한 가비지 수거)를 수행합니다. 메모리는 마지막 참조가 제거된 직후에 해제됩니다.


Python は自動的にメモリを管理します (ほとんどのオブジェクトは参照カウント方式で管理し、ガベージコレクション(garbage collection)で循環参照を除去します)。オブジェクトに対する最後の参照がなくなってしばらくするとメモリは解放されます。


이 접근법은 대부분의 응용 프로그램에서 잘 작동하지만, 때로는 다른 것들에 의해 사용되는 동안에만 객체를 추적해야 할 필요가 있습니다. 불행하게도, 단지 그것들을 추적하는 것만으로도 그들을 영구적으로 만드는 참조를 만듭니다. weakref 모듈은 참조를 만들지 않고 객체를 추적할 수 있는 도구를 제공합니다. 객체가 더 필요하지 않으면 weakref 테이블에서 객체가 자동으로 제거되고 weakref 객체에 대한 콜백이 트리거됩니다. 일반적인 응용에는 만드는 데 비용이 많이 드는 개체 캐싱이 포함됩니다:

このようなアプローチはほとんどのアプリケーションでうまく動作しますが、中にはオブジェクトをどこか別の場所で利用している間だけ追跡しておきたい場合もあります。残念ながら、オブジェクトを追跡するだけでオブジェクトに対する恒久的な参照を作ることになってしまいます。 weakref モジュールでは、オブジェクトへの参照を作らずに追跡するためのツールを提供しています。弱参照オブジェクトが不要になると、弱参照 (weakref) テーブルから自動的に除去され、コールバック関数がトリガされます。弱参照を使う典型的な応用例には、作成コストの大きいオブジェクトのキャッシュがあります:

>>>
>>> import weakref, gc
>>> class A:
...     def __init__(self, value):
...         self.value = value
...     def __repr__(self):
...         return str(self.value)
...
>>> a = A(10)                   # create a reference
>>> d = weakref.WeakValueDictionary()
>>> d['primary'] = a            # does not create a reference
>>> d['primary']                # fetch the object if it is still alive
10
>>> del a                       # remove the one reference
>>> gc.collect()                # run garbage collection right away
0
>>> d['primary']                # entry was automatically removed
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
    d['primary']                # entry was automatically removed
  File "C:/python37/lib/weakref.py", line 46, in __getitem__
    o = self.data[key]()
KeyError: 'primary'


11.7. 리스트 작업 도구  リスト操作のためのツール


내장 리스트 형으로 많은 데이터 구조 요구를 충족시킬 수 있습니다.  그러나 때로는 다른 성능 상충 관계가 있는 대안적 구현이 필요할 수도 있습니다.

多くのデータ構造は、組み込みリスト型を使った実装で事足ります。とはいえ、時には組み込みリストとは違うパフォーマンス上のトレードオフを持つような実装が必要になこともあります。


array 모듈은 array() 객체를 제공

 이 객체는 등질적인 데이터만을 저장하고 보다 조밀하게 저장하는 리스트와 같습니다. 

다음 예제는 파이썬 int 객체의 일반 리스트의 경우처럼 항목당 16바이트를 사용하는 대신에, 2바이트의 부호 없는 이진 숫자 (형 코드 "H")로 저장된 숫자 배열을 보여줍니다:

array (配列) モジュールでは、array() オブジェクトを提供しています。配列はリストに似ていますが、同じ形式のデータだけが保存でき、よりコンパクトに保存されます。以下の例では、通常 1 要素あたり 16 バイトを必要とする Python 整数型のリストの 代りに、2 バイトの符号無しの 2 進数 (タイプコード "H") の配列を使っています:

>>>
>>> from array import array
>>> a = array('H', [4000, 10, 700, 22222])
>>> sum(a)
26932
>>> a[1:3]
array('H', [10, 700])


collections 모듈은 deque() 객체를 제공합니다. 

이 객체는 왼쪽에서 더 빠르게 추가/팝하지만 중간에서의 조회는 더 느려진 리스트와 같습니다. 

이 객체는 대기열 및 넓이 우선 트리 검색을 구현하는 데 적합합니다:

collections モジュールでは、deque() オブジェクトを提供しています。リスト型に似ていますが、データの追加と左端からの取り出しが速く、その一方で中間にある値の参照は遅くなります。こうしたオブジェクトはキューや木構造の幅優先探索の実装に向いています:

>>>
>>> from collections import deque
>>> d = deque(["task1", "task2", "task3"])
>>> d.append("task4")
>>> print("Handling", d.popleft())
Handling task1
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 모듈과 같은 다른 도구를 제공합니다:

リストの代わりの実装以外にも、標準ライブラリにはソート済みのリストを操作するための関数を備えた bisect のようなツールも提供しています:

>>>
>>> import bisect
>>> scores = [(100, 'perl'), (200, 'tcl'), (400, 'lua'), (500, 'python')]
>>> bisect.insort(scores, (300, 'ruby'))
>>> scores
[(100, 'perl'), (200, 'tcl'), (300, 'ruby'), (400, 'lua'), (500, 'python')]


heapq 모듈은 일반 리스트를 기반으로 힙을 구현하는 함수를 제공합니다. 가장 값이 작은 항목은 항상 위치 0에 유지됩니다. 이것은 가장 작은 요소에 반복적으로 액세스하지만, 전체 목록 정렬을 실행하지 않으려는 응용에 유용합니다:

heapq モジュールは、通常のリストでヒープを実装するための関数を提供しています。ヒープでは、最も低い値をもつエントリがつねにゼロの位置に配置されます。ヒープは、毎回リストをソートすることなく、最小の値をもつ要素に繰り返しアクセスするようなアプリケーションで便利です:

>>>
>>> from heapq import heapify, heappop, heappush
>>> data = [1, 3, 5, 7, 9, 2, 4, 6, 8, 0]
>>> heapify(data)                      # rearrange the list into heap order
>>> heappush(data, -5)                 # add a new entry
>>> [heappop(data) for i in range(3)]  # fetch the three smallest entries
[-5, 0, 1]


11.8. 10진 부동 소수점 산술 10 進浮動小数演算

decimal 모듈은 10진 부동 소수점 산술을 위한 Decimal 데이터형을 제공합니다. 내장 float 이진 부동 소수점 구현과 비교할 때, 클래스는 특히 다음과 같은 것들에 유용합니다

decimal モジュールでは、 10 進浮動小数の算術演算をサポートする Decimal データ型を提供しています。組み込みの 2 進浮動小数の実装である float に比べて、このクラスがとりわけ便利なのは、以下の場合です

  • 정확한 10진수 표현이 필요한 금융 응용 및 기타 용도,
  • 정밀도 제어,
  • 법적 또는 규제 요구 사항을 충족하는 반올림 제어,
  • 유효숫자 추적, 또는
  • 사용자가 결과가 손으로 계산한 것과 일치 할 것으로 기대하는 응용.
  • 財務アプリケーションやその他の正確な10進表記が必要なアプリケーション、
  • 精度の制御、
  • 法的または規制上の理由に基づく値丸めの制御、
  • 有効桁数の追跡が必要になる場合
  • ユーザが手計算の結果と同じ演算結果を期待するようなアプリケーション。

예를 들어, 70센트 전화 요금에 대해 5% 세금을 계산하면, 십진 부동 소수점 및 이진 부동 소수점에 다른 결과가 나타납니다. 결과를 가장 가까운 센트로 반올림하면 차이가 드러납니다:

例えば、70 セントの電話代にかかる 5% の税金を計算しようとすると、10 進の浮動小数点値と 2 進の浮動小数点値では違う結果になってしまいます。計算結果を四捨五入してセント単位にしようとすると、以下のように違いがはっきり現れます:

>>>
>>> from decimal import *
>>> round(Decimal('0.70') * Decimal('1.05'), 2)
Decimal('0.74')
>>> round(.70 * 1.05, 2)
0.73


Decimal 결과는 끝에 붙는 0을 유지하며, 두 개의 유효숫자를 가진 피승수로부터 네 자리의 유효숫자를 자동으로 추론합니다. Decimal은 손으로 한 수학을 재현하고 이진 부동 소수점이 십진수를 정확하게 표현할 수 없을 때 발생할 수 있는 문제를 피합니다.

上の例で、Decimal を使った計算では、末尾桁のゼロが保存されており、有効数字2桁の被乗数から自動的に有効数字を 4 桁と判断しています。Decimal は手計算と 同じ方法で計算を行い、2 進浮動小数が 10 進小数成分を正確に表現できないことに よって起きる問題を回避しています。


정확한 표현은 Decimal 클래스가 이진 부동 소수점에 적합하지 않은 모듈로 계산과 동등성 검사를 수행할 수 있도록 합니다:

Decimal クラスは厳密な値を表現できるため、2 進浮動小数点数では 期待通りに計算できないような剰余の計算や等値テストも実現できます

>>>
>>> Decimal('1.00') % Decimal('.10')
Decimal('0.00')
>>> 1.00 % 0.10
0.09999999999999995

>>> sum([Decimal('0.1')]*10) == Decimal('1.0')
True
>>> sum([0.1]*10) == 1.0
False


decimal 모듈은 필요한 만큼의 정밀도로 산술을 제공합니다:

decimal モジュールを使うと、必要なだけの精度で算術演算を行えます:

>>>
>>> getcontext().prec = 36
>>> Decimal(1) / Decimal(7)
Decimal('0.142857142857142857142857142857142857')