# 10. 표준 라이브러리 둘러보기

## 10.1. 운영 체제 인터페이스

`os` 모듈은 운영 체제와 상호 작용하기 위한 수십 가지 함수들을 제공합니다:

    >>> import os
    >>> os.getcwd()      # 현재 작업 디렉터리를 돌려줍니다
    'C:\\Python313'
    >>> os.chdir('/server/accesslogs')   # Change current working directory
    >>> os.system('mkdir today')   # Run the command mkdir in the system shell
    0

`from os import *` 대신에 `import os` 스타일을 사용해야 합니다. 그래야 `os.open()` 이 내장 `open()` 을 가리는 것을 피할 수 있는데, 두 함수는 아주 다르게 동작합니다.

`os` 와 같은 큰 모듈과 작업할 때, 내장 `dir()` 과 `help()` 함수는 대화형 도우미로 쓸모가 있습니다.

    >>> import os
    >>> dir(os)
    <returns a list of all module functions>
    >>> help(os)
    <returns an extensive manual page created from the module's docstrings>

일상적인 파일과 디렉터리 관리 작업을 위해, `shutil` 모듈은 사용하기 쉬운 더 고수준의 인터페이스를 제공합니다:

    >>> import shutil
    >>> shutil.copyfile('data.db', 'archive.db')
    'archive.db'
    >>> shutil.move('/build/executables', 'installdir')
    'installdir'

## 10.2. 파일 와일드카드

`glob` 모듈은 디렉터리 와일드카드 검색으로 파일 목록을 만드는 함수를 제공합니다:

    >>> import glob
    >>> glob.glob('*.py')
    ['primes.py', 'random.py', 'quote.py']

## 10.3. 명령행 인자

일반적인 유틸리티 스크립트는 종종 명령행 인자를 처리해야 할 필요가 있습니다. 이 인자들은 `sys` 모듈의 argv 어트리뷰트에 리스트로 저장됩니다. 예를 들어, 다음과 같은 `demo.py` 파일을 보겠습니다:

    # 파일 demo.py
    import sys
    print(sys.argv)

다음은 명령행에서 `python demo.py one two three` 를 실행한 출력입니다:

    ['demo.py', 'one', 'two', 'three']

`argparse` 모듈은 명령 줄 인자를 처리하는 더 정교한 메커니즘을 제공합니다. 다음 스크립트는 하나 이상의 파일명과 선택적으로 표시할 줄 수를 추출합니다:

    import argparse

    parser = argparse.ArgumentParser(
        prog='top',
        description='Show top lines from each file')
    parser.add_argument('filenames', nargs='+')
    parser.add_argument('-l', '--lines', type=int, default=10)
    args = parser.parse_args()
    print(args)

`python top.py --lines=5 alpha.txt beta.txt`를 사용하여 명령 줄에서 실행할 때, 스크립트는 `args.lines`를 `5`로, `args.filenames`를 `['alpha.txt', 'beta.txt']`로 설정합니다.

## 10.4. 에러 출력 리디렉션과 프로그램 종료

`sys` 모듈은 stdin, stdout, stderr 어트리뷰트도 갖고 있습니다. 가장 마지막 것은 stdout 이 리디렉트 되었을 때도 볼 수 있는 경고와 에러 메시지들을 출력하는데 쓸모가 있습니다:

    >>> sys.stderr.write('Warning, log file not found starting a new one\n')
    Warning, log file not found starting a new one

스크립트를 종료하는 가장 직접적인 방법은 `sys.exit()` 를 쓰는 것입니다.

## 10.5. 문자열 패턴 매칭

`re` 모듈은 고급 문자열 처리를 위한 정규식 도구들을 제공합니다. 복잡한 매칭과 조작을 위해, 정규식은 간결하고 최적화된 솔루션을 제공합니다:

    >>> import re
    >>> re.findall(r'\bf[a-z]*', 'which foot or hand fell fastest')
    ['foot', 'fell', 'fastest']
    >>> re.sub(r'(\b[a-z]+) \1', r'\1', 'cat in the the hat')
    'cat in the hat'

단지 간단한 기능만 필요한 경우에는, 문자열 메서드들이 선호되는데 읽기 쉽고 디버깅이 쉽기 때문입니다:

    >>> 'tea for too'.replace('too', 'two')
    'tea for two'

## 10.6. 수학

`math` 모듈은 부동 소수점 연산을 위한 하부 C 라이브러리 함수들에 대한 액세스를 제공합니다.

    >>> import math
    >>> math.cos(math.pi / 4)
    0.70710678118654757
    >>> math.log(1024, 2)
    10.0

`random` 모듈은 무작위 선택을 할 수 있는 도구들을 제공합니다:

    >>> import random
    >>> random.choice(['apple', 'pear', 'banana'])
    'apple'
    >>> random.sample(range(100), 10)   # 대체 없는 표본 추출
    [30, 83, 16, 4, 8, 81, 41, 50, 18, 33]
    >>> random.random()    # 범위 [0.0, 1.0) 내에서의 임의의 float
    0.17970987693706186
    >>> random.randrange(6)    # range(6) 에서 선택된 임의의 정수
    4

`statistics` 모듈은 수치 데이터의 기본적인 통계적 특성들을 (평균, 중간값, 분산, 등등) 계산합니다.

    >>> import statistics
    >>> data = [2.75, 1.75, 1.25, 0.25, 0.5, 1.25, 3.5]
    >>> statistics.mean(data)
    1.6071428571428572
    >>> statistics.median(data)
    1.25
    >>> statistics.variance(data)
    1.3720238095238095

SciPy 프로젝트 <https://scipy.org> 는 다른 수치 계산용 모듈들을 많이 갖고 있습니다.

## 10.7. 인터넷 액세스

인터넷을 액세스하고 인터넷 프로토콜들을 처리하는 많은 모듈이 있습니다. 가장 간단한 두 개는 URL에서 데이터를 읽어오는 `urllib.request` 와 메일을 보내는 `smtplib` 입니다:

    >>> from urllib.request import urlopen
    >>> with urlopen('http://worldtimeapi.org/api/timezone/etc/UTC.txt') as response:
    ...     for line in response:
    ...         line = line.decode()             # bytes 를 str 로 변환합니다
    ...         if line.startswith('datetime'):
    ...             print(line.rstrip())         # 후행 줄 넘김을 제거합니다
    ...
    datetime: 2022-01-01T01:36:47.689215+00:00

    >>> import smtplib
    >>> server = smtplib.SMTP('localhost')
    >>> server.sendmail('soothsayer@example.org', 'jcaesar@example.org',
    ... """To: jcaesar@example.org
    ... From: soothsayer@example.org
    ...
    ... Beware the Ides of March.
    ... """)
    >>> server.quit()

(두 번째 예는 localhost 에서 메일 서버가 실행되고 있어야 한다는 것에 주의하세요.)

## 10.8. 날짜와 시간

`datetime` 모듈은 날짜와 시간을 조작하는 클래스들을 제공하는데, 간단한 방법과 복잡한 방법 모두 제공합니다. 날짜와 시간 산술이 지원되지만, 구현의 초점은 출력 포매팅과 조작을 위해 효율적으로 멤버를 추출하는 데에 맞춰져 있습니다. 모듈은 시간대를 고려하는 객체들도 지원합니다.

    >>> # 날짜는 쉽게 구성되고 포맷됩니다
    >>> from datetime import date
    >>> now = date.today()
    >>> now
    datetime.date(2003, 12, 2)
    >>> now.strftime("%m-%d-%y. %d %b %Y is a %A on the %d day of %B.")
    '12-02-03. 02 Dec 2003 is a Tuesday on the 02 day of December.'

    >>> # 날짜는 캘린더 산술을 지원합니다
    >>> birthday = date(1964, 7, 31)
    >>> age = now - birthday
    >>> age.days
    14368

## 10.9. 데이터 압축

일반적인 데이터 보관 및 압축 형식들을 다음과 같은 모듈들이 직접 지원합니다: `zlib`, `gzip`, `bz2`, `lzma`, `zipfile`, `tarfile`.

    >>> import zlib
    >>> s = b'witch which has which witches wrist watch'
    >>> len(s)
    41
    >>> t = zlib.compress(s)
    >>> len(t)
    37
    >>> zlib.decompress(t)
    b'witch which has which witches wrist watch'
    >>> zlib.crc32(s)
    226805979

## 10.10. 성능 측정

일부 파이썬 사용자들은 같은 문제에 대한 다른 접근법들의 상대적인 성능을 파악하는데 깊은 관심을 두고 있습니다. 파이썬은 이런 질문들에 즉시 답을 주는 측정 도구를 제공합니다.

예를 들어, 인자들을 맞교환하는 전통적인 방식 대신에, 튜플 패킹과 언 패킹을 사용하고자 하는 유혹을 느낄 수 있습니다. `timeit` 모듈은 적당한 성능 이점을 신속하게 보여줍니다:

    >>> from timeit import Timer
    >>> Timer('t=a; a=b; b=t', 'a=1; b=2').timeit()
    0.57535828626024577
    >>> Timer('a,b = b,a', 'a=1; b=2').timeit()
    0.54962537085770791

`timeit` 의 정밀도와는 대조적으로, `profile` 과 `pstats` 모듈은 큰 블록의 코드에서 시간 임계 섹션을 식별하기 위한 도구들을 제공합니다.

## 10.11. 품질 관리

고품질의 소프트웨어를 개발하는 한 가지 접근법은 개발되는 각 함수에 대한 테스트를 작성하고, 그것들을 개발 프로세스 중에 자주 실행하는 것입니다.

`doctest` 모듈은 모듈을 훑어보고 프로그램의 독스트링들에 내장된 테스트들을 검사하는 도구를 제공합니다. 테스트 만들기는 평범한 호출을 그 결과와 함께 독스트링으로 복사해서 붙여넣기를 하는 수준으로 간단해집니다. 사용자에게 예제를 함께 제공해서 설명서를 개선하고, doctest 모듈이 설명서에서 코드가 여전히 사실인지 확인하도록 합니다.

    def average(values):
        """숫자 목록의 산술 평균을 계산합니다.

        >>> print(average([20, 30, 70]))
        40.0
        """
        return sum(values) / len(values)

    import doctest
    doctest.testmod()   # 내장된 테스트를 자동 검증합니다

`unittest` 모듈은 `doctest` 모듈만큼 쉬운 것은 아니지만, 더욱 포괄적인 테스트 집합을 별도의 파일로 관리할 수 있게 합니다:

    import unittest

    class TestStatisticalFunctions(unittest.TestCase):

        def test_average(self):
            self.assertEqual(average([20, 30, 70]), 40.0)
            self.assertEqual(round(average([1, 5, 7]), 1), 4.3)
            with self.assertRaises(ZeroDivisionError):
                average([])
            with self.assertRaises(TypeError):
                average(20, 30, 70)

    unittest.main()  # 명령행에서 호출하면 모든 테스트를 수행합니다

## 10.12. 배터리가 포함됩니다

파이썬은 “배터리가 포함됩니다” 철학을 갖고 있습니다. 이는 더 큰 패키지의 정교하고 강력한 기능을 통해 가장 잘 나타납니다. 예를 들어:

- `xmlrpc.client` 와 `xmlrpc.server` 모듈은 원격 프로시저 호출을 구현하는 일을 거의 사소한 일로 만듭니다. 모듈의 이름에도 불구하고, XML에 대한 직접적인 지식이나 처리가 필요하지 않습니다.

- `email` 패키지는 MIME 및 기타 RFC 2822 기반 메시지 문서를 포함하는 전자 메일 메시지를 관리하기 위한 라이브러리입니다. 실제로 메시지를 보내고 받는 `smtplib` 와 `poplib` 와는 달리, email 패키지는 복잡한 메시지 구조 (첨부 파일 포함) 를 작성하거나 해독하고 인터넷 인코딩과 헤더 프로토콜을 구현하기 위한 완벽한 도구 상자를 가지고 있습니다.

- `json` 패키지는 널리 사용되는 데이터 교환 형식을 파싱하기위한 강력한 지원을 제공합니다. `csv` 모듈은 데이터베이스와 스프레드시트에서 일반적으로 지원되는 쉼표로 구분된 값 형식으로 파일을 직접 읽고 쓸 수 있도록 지원합니다. XML 처리는 `xml.etree.ElementTree`, `xml.dom` 및 `xml.sax` 패키지에 의해 지원됩니다. 이러한 모듈과 패키지를 함께 사용하면 파이썬 응용 프로그램과 다른 도구 간의 데이터 교환이 크게 단순해집니다.

- `sqlite3` 모듈은 SQLite 데이터베이스 라이브러리의 래퍼인데, 약간 비표준 SQL 구문을 사용하여 업데이트되고 액세스 될 수 있는 퍼시스턴트 데이터베이스를 제공합니다.

- 국제화는 `gettext`, `locale`, 그리고 `codecs` 패키지를 포함한 많은 모듈에 의해 지원됩니다.