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


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

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

   >>> import os
   >>> os.getcwd()      # Return the current working directory
   'C:\\Python312'
   >>> 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)   # sampling without replacement
   [30, 83, 16, 4, 8, 81, 41, 50, 18, 33]
   >>> random.random()    # random float
   0.17970987693706186
   >>> random.randrange(6)    # random integer chosen from 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" 패키지를 포함한 많은
  모듈에 의해 지원됩니다.
