제공: 한빛 네트워크
저자: Jeff Cogswell, 추홍엽 역
원문: What"s New in Python 2.5
파이썬(python)이 나온지 벌써 15년이 넘었다는게 믿기 어렵다. 15년이란 시간이 하나의 프로그래밍 언어로서 낡아 보일 수 있는 반면, 파이썬의 경우에 그것은 이 언어가 성숙했음을 의미한다. 그 나이에도 불구하고 파이썬의 새 버전은 강력하며 현대 프로그래밍 언어로부터 기대되는 모든 것을 제공한다.
본 기사에서는 파이썬 2.5의 새롭고 중요한 특징들을 간략히 소개한다. 필자는 여러분이 파이썬에 친숙하며 입문 튜토리얼을 찾고 있는 것이 아니라고 가정한다. 다만 일부 경우에는 제네레이터와 같은 몇가지 자료를 소개하겠다.
언어 그 자체로서의 변화와 강화
파이썬 2.5는 언어로의 수많은 유용한 개선사항을 포함한다. 커다란 변화는 없으며 기존의 2.4버전 코드에해 변경을 필요로 하지도 않는다.
조건 표현식
다른 언어들, 특히 C와 C++는 수년동안 if 문을 포함한 조건 표현식들을 허용해 왔다. 기본 생각은 단순하다: 한 변수가 있는데 임의의 조건이 참일 때 그 변수를 어떤 값으로 설정하고 싶고, 거짓이면 다른 값으로 설정하고 싶다.
분명, 파이썬에서 다음과 같은 블록 if문을 사용하여 언제든지 이를 할 수 있다:
if x > 15:
a = 1
else:
a = 2
그러나 많은 프로그래머들이 단축형을 더 선호한다. C 언어는 같은 할당식을 한 줄에 행할 수 있는 아이디어를 도입했다:
a = x > 15 ? 1 : 2;
C 코드에서 x > 15라는 조건문이 참이면 표현식의 값은 1이고 그렇지 않으면 값은 2이다.
파이썬 2.5는 이제 비슷한 특징을 갖는다. 파이썬의 형식은 약간 재수정되었다:
a = 1 if x > 15 else 2
정적으로 타입을 가지는 C나 C++와 같은 다른 언어들에도 조건 표현식이 존재하지만 파이썬의 타입 체계는 다르다. 이 새로운 특징을 살펴보는 동안 필자는 구조체의 중간에서 타입을 수정할 수 있는지 궁금했었다. 다음과 같이 말이다:
a = "abc" if x > 15 else 10
이것은 잘 돌아간다. 물론, 버그를 가져올수 있다는 점에서 이는 아마도 가장 안전한 코드는 아니겠지만, 그렇게 하는 합당한 이유가 있다면 다른 타입을 사용할 수 있다.
장기적인 예외 처리의 가벼운 변화
파이썬 2.5에는 Exception 클래스 계층 구조가 변화했다. 일반적으로 변경점들은 대부분 파이썬 3.0을 준비하는 과도기적인 변화들이며, 이와 함께 어떤 2.5버전 이전의 기능들은 사용이 비권장(deprecated) 되었다. 이는 여전히 이전의 기능들을 사용할 수는 있다는 것을 의미하지만 언어차원에서는 그렇게 하는 것을 권하지 않으며, 이것은 파이썬 3.0에 이르러서는 더 이상 그 기능들이 작동하지 않을 것이기 때문이다.
새롭게 비권장된 기능중의 하나는 예외로써 문자열을 일으키는 용법이다. 이전에는 (필자는 파이썬 2.4.3 버전을 사용했다) 다음과 같은 코드를 작성할 수 있었다:
>>> raise "Invalid argument"
Traceback (most recent call last):
File "", line 1, in ?
Invalid argument
>>>
파이썬 2.5에서는, 여전히 예외로서의 문자열을 일으킬 수 있지만, 비권장 경고도 뜬다.
>>> raise "Invalid argument"
__main__:1: DeprecationWarning: raising a string exception
is deprecated
Traceback (most recent call last):
File "", line 1, in
Invalid argument
>>>
그러나, 파이썬 세션마다 처음에만 경고가 뜰뿐이다. 이 다음번부터는 경고가 뜨지 않는다. 파이썬 2.5는 이런식으로 코드를 작성하는 것을 중단하길 권한다. 파이썬 3.0이 되면 코드는 컴파일되지 않을 것이기 때문이다.
예외의 문자열을 일으키는 것에 대한 비권장 외에도 파이썬 2.5는 예외 클래스 계층구조를 재정리 했다. 새로운 BaseException 클래스가 Exception에 대한 기본 클래스이다. 이제 모든 사용자 정의 예외 클래스들은 Exception클래스를 상속하거나 Exception클래스를 상속한 클래스에서 파생되어야 한다.
다른 두개의 예외 클래스, KeyboardInterrupt와 SystemExit 또한 Exception가 아닌 BaseException를 상속했다. 그러므로 여러분 자신만의 예외를 잡아낼 수 있고, 그러면 Exception에서 파생된 다른 모든 예외들을 잡아낼 수 있다. 이는 KeyboardInterrupt와 SystemExit를 제외한 모든 예외를 잡아낼 것이다. 왜 이 두 예외는 잡아내려하지 않는 것인가? Ctrl+C를 수동으로 잡아서 응답을 해주거나 Ctrl+C를 잡는 것을 생략하여 시스템이 그것을 다루도록 수동으로 하지 않는다면 사용자가 Ctrl+C를 눌렀을 때 프로그램은 종료될 것이다.
그러고 보면 이 새로운 특징은, 특징이라기 보다는 필수사항에 가깝다: 자신의 예외클래스를 Exception을 상속하여 다시 작성하라. 그러면 파이썬 3.0에서는 문제없을 것이다.
마지막으로 파이썬에서 앞으로의 예외처리에 관한 또다른 작은 경고를 하나 하려한다. 현재 예외 클래스들은 message와 args 둘 다 멤버로 가진다. 일반적인 생각은 message는 문자열이 되고, args는 예외에 전하는 추가적인 인수들의 리스트였다. 그러나 이것은 불필요한 중복이다. 왜냐하면 message는 문자열이 될 필요가 없기 때문이다. 그래서 파이썬 3.0은 더 이상 args를 가지지 않을 것이다. 그러므로 args에 대한 사용을 중단해야 한다.
향상된 예외 처리
파이썬 2.5에서는 계층 구조의 변화 외에도 try 메커니즘이 강화되었다. 이전에는 두 겹의 예외를 사용하지 않으면 except와 finally 블록을 섞어서 사용할 수 없었다. 이제 두개를 하나의 블록 내에서 같이 사용할 수 있다. 참 살기 편해졌다. 그러나, 순서가 중요하다. 반드시 try블록을 가장 처음에 사용하고, 그리고 추가적인 예외 핸들러를, 그리고 아무런 예외가 발생하지 않았을 때 실행되는 else 블록을 추가적으로 사용하고, 그리고 모든 경우에 실행되는 finally블록을 사용한다. 다음은 그 예이다:
try:
test()
except ZeroDivisionError:
print "The expression resulted in a division-by-zero error"
except Exception:
print "Oops"
else:
print "All is good"
finally:
print "And everything is finished"
이전 버전에서는 두개의 try블록을 사용하여 한 블록이 다른 블록 내에 위치하고 바깥쪽 블록이 finally 블록을 가져야 했다. 이제는 이 모든 것을 단일 블록 내에서 할 수 있다.
값을 반환하는 제네레이터
제네레이터는 파이썬 2.3버전에서 언어에 포함되었다. 버전 2.5는 제네레이트의 성능을 확장한다.
제네레이터 나가고 들어오고 할 수 있는 함수이고 순환문에 유용하다. 예를 들어, 다음은 iterate라 불리우는 제네레이터를 포함한 클래스이다.
class MyStuff:
def __init__(self):
self.a = [2,4,6,8,10,12]
def iterate(self):
i = 0
while i < len(self.a):
yield self.a[i]
i += 1
이 코드는 제네레이터를 이용하는데 순환문을 설명해 보면,
obj = MyStuff()
iterate = obj.iterate()
print iterate.next()
print iterate.next()
print iterate.next()
첫번째 라인은 MyStuff 클래스의 인스턴스를 생성한다. 두번째 라인은 인스턴스로부터 이터레이터를 꺼낸다. 이터레이터 자체는 제네레이터에서 얻은 값이 아님을 주의하자. 대신에 값을 얻기 위해 next를 부를 수 있다. 만약 인터랙티브 셸에서라면 이터레이터의 값을 얻으려 할 때 무슨일이 생기는지 볼 수 있다:
>>> print iterate
>>>
이것이 C++에서의 이터레이터와 다른 점이다. C++에서는 값을 얻기 위해 디레퍼런스(dereference)할 수 있지만 파이썬에서 제네레이터는 내장 제네레이터 오브젝트이다.
제네레이터에 깔린 기본 아이디어는 yield문을 포함한 함수를 호출하는 것이다. yield문은 중단과 리턴을 위한 함수를 실행 시킨다. 그리고나서 함수안으로 돌아갈 수 있는데 next()를 호출해서 남아 있는 것을 선택한다. 그러므로 다음을 호출했을 때:
iterate.next()
… 예외는 함수안으로 단계진행되어 처음 두 라인(할당문과 while루프의 첫라인)을 실행한다. 다음 라인은 yield문인데 호출자로의 리턴을 실행한다. 여기서는 임시적으로 self.a[i]값을 반환한다.
그후 iterate.next()를 다시 호출하면 실행은 yield문 다음에서 i값이 증가된 채로 재개된다.while 루프는 다음 yield문이 나올때까지 다시 계속 된다.
주의할 것은 iterate = obj.iterate()로 제네레이터를 생성하는 것이 실제적으로 함수 내로 호출하지는 않는다는 것이다. 파이썬 컴파일러는 함수내의 yield문을 보고 그것을 하나의 이터레이터로 식별했고, 대신에 제네레이터 오브젝트를 생성하는 함수를 호출했다. Iterate함수에 print문을 삽입하면 이를 확인할 수 있다.
def iterate(self):
print "Creating iterator"
i = 0
...rest of code...
iterate = obj.iterate()을 호출했을 때는 "Creating iterator"라는 출력을 볼 수 없지만 첫번째 next 호출인 print iterate.next()를 했을 때 이것을 볼 수 있다.
이상이 제네레이터에 대한 간략한 소개였고 이것은 파이썬 2.5에서 새로운 내용이 아니다. 그러나 사람들은 제네레이터 기능에서 결점들을 발견했다. 제네레이터를 제공하는 언어들에서 중요한 기능은 제네레이터로 값을 되돌려 넘겨줄 수 있는 것이다. 이것은 coroutines라고 불리우는 프로그래밍 특성을 지원가능케 한다.
제네레이터를 더욱 강력하게 하기 위해서 파이썬의 디자이너들은 제네레이터로 데이터를 되돌려 넘겨줄수 있는 기능을 추가 했다. 만약 제네레이터의 관점에서 볼 때 yield를 무엇인가를 호출하는 것으로 생각한다면 개념은 쉽다: yeild의 결과값을 저장만 하면 된다:
x = yield y
제네레이터의 호출자 관점에서 보면, 이 문장은 전처럼 호출자로 제어를 넘긴다. 제네레이터의 관점에서 실행이 제네레이터에게 다시 돌아 왔을 때 값이 같이 따라오게 될 것이다 - 이경우에 제네레이터는 변수 x에 그 값을 저장한다.
이 값은 어디서 오는가? 호출자는 제네레이터로 값을 돌려 보내기 위해 send()라는 함수를 호출한다. 함수send()는 값을 보내는 것을 제외하고는 함수next()와 똑같이 행동한다.
다음은 send()를 사용하는 방법을 설명하는 약간의 수정된 코드이다. 이 경우에 필자는 send()를 제네레이터의 사용자가 배열에서 인덱스를 다시 조정할 수 있게 사용하였다. 그러나 보내지는 값이 배열의 경계 내에 확실히 속해있게 하였다. 한편 가장 가까운 경계값으로 설정했다.
class MyStuff:
def __init__(self):
self.a = [2,4,6,8,10,12]
def iterate(self):
i = 0
while i < len(self.a):
val = yield self.a[i]
if val == None:
i += 1
else:
if val < 0:
val = 0
if val >= len(self.a):
val = len(self.a) -1
i = val
주의 깊게 살펴 볼 것은 제네레이터가 받아서 val에 저장한 값을 어떻게 테스트 했는가이다. 만약 val이 None이면 제네레이터가 아무 값도 받지 않았다는 것을 의미한다. (호출하는 쪽 코드는 next()를 사용했거나 아니면 아마도 send(None)를 사용) 그러나 그 값이 들어왔다면 배열의 경계를 정하고 인덱스에 그것을 저장할 것이다.
우연하게도 필자는 처음에 i의 값을 설정하기 위하여 두개의 if 문을 사용하는 대신에 새로운 조건표현식 기능을 사용하여 시도했었다. 앞선 코드에서 else라인 다음의 라인들을 줄일 수 있다.
i = val if (val >= 0 and val < max) else (0 if val < 0 else max)
개인적으로 한 줄에 모든 것을 작성하는 것은 다소 읽기 힘들고 그 수많은 오래된 C 코드에서 한때 도졌던 그 알아보기 힘들게 하는 전염병으로 고생하게 만든다고 생각한다. 그러므로 필자는 좀 더 길게 작성하는 버전을 채택했다. (그러나 이 압축된 라인은 같은 C 코드보다 더 읽기 쉽다는 것을 반드시 말해둬야 할 것 같다.)
제네레이터 코드가 실행 될 때 예외를 던진다. 원한다면 next() 호출을 통해 루프를 돌릴수 있고 try/catch 블록으로 감쌀수 있다. 대신에 반복의 끝을 가리키기 위한 값을 반환하는 yield 호출을 만들수 있다. 다음은 이전 코드에서 생성자 부분을 수정한 것이다:
def __init__(self):
self.a = [2,4,6,8,10,12, None]
필자는 리스트의 끝에 단순히 None을 추가 했다. 그러면 예외를 잡지 않게 하고 리스트의 끝에 대한 테스트를 지켜볼 수 있다.
obj = MyStuff()
iterate = obj.iterate()
a = iterate.next()
while a != None:
print a
a = iterate.next()
iterate.close()
마지막 라인은 close() 함수를 호출하는데 이것 역시 파이썬 2.5에서 제네레이터에 새롭게 추가된 것이다. 이것은 제네레이터에 대한 자원을 풀어주는 역할을 한다. 만약 iterate.close()을 호출한 후에 iterate.next()를 다시 호출하면 StopIteration 예외가 발생 할 것이다.
여러분이 만약 파이썬의 최근 버전들에 익숙하다면 내장된 파이썬 iter() 함수가 어디에 알맞게 되어 있는가 궁금할 것이다. 여기에 대한 대답은 만약 제네레이터 함수 이름을 iter__()로 지으면 제네레이터는 자동적으로 iter() 함수와 작동할 것이라는 것이다. 이 기능은 파이썬 2.4에도 존재했지만, 파이썬 2.5에서는 iter()와 함께 send() 함수를 사용할 수 있다. 앞의 MyStuff 예제에서 iterator() 함수의 이름을 __iter__로 바꾸고 나머지는 그대로 둔다면, iter 함수는 대강 이렇게 작동할 것이다.
>>> obj = gen1.MyStuff2()
>>> i = iter(obj)
>>> i.next()
2
>>> i.send(3)
8
>>> i.next()
10
컨텍스트 관리
파이썬에서 이제 with문을 사용할 수 있게 되었다. 많은 언어들이 with문을 가지고 있지만 보통 파이썬에서의 with문과는 틀리다. 파이썬에서 with의 목적은 특정 컨텍스트하에 실행되는 코드 블록을 만들기 위한 것이다. 해당 코드 블록이 실행된 후에 이 컨텍스트가 종료되면 어떤 클린업(cleanup) 코드를 실행한다.
컨텍스트란 무엇인가? 일반적인 예로는 데이터베이스 트랜잭션의 예를 들수 있다. 데이터베이스 트랜잭션에서는, 트랜잭션을 시작하고, 데이터베이스에 대한 변경을 가한다. 그리고 나서 모든 변경에 대해 그것을 취소할 것인지 (혹은 "롤백" ) 아니면 반영할 것인지 (즉, 영원히 변경할 것인지) 결정할 수 있다. 그리고 나면 트랜잭션이 종료된다.
데이터베이스를 변경하고 있는 동안은 특정 데이터베이스 트랜잭션의 컨텍스트 하에 실행되고 있는 것이다. 컨텍스트는 트랜잭션이 시작될 때 (트랜잭션을 생성하고 필요 자원을 할당하는) 어떤 코드를 수행하고 마지막에 (변경을 반영하던 롤백하던 간에) 또 어떤 코드를 수행한다.
컨텍스트는 트랜잭션 그 자체이지, 롤백이나 반영이 아니다. 컨텍스트는 필수적으로 롤백이나 반영을 포함할 필요는 없다.
또 다른 예는 파일이 열려지고 있을 때의 예이다. 파일은 열고, 쓰고, 닫을 수 있다. 파일을 쓰고 있는 동안은 코드를 파일의 컨텍스트 하에 작동하고 있는 것으로 생각할 수 있다. 그리고 나서 컨텍스트는 파일을 열 수 있고, 그 파일에 대한 작업이 끝났을 때 파일을 닫는 작업을 다룰 수 있다.
컨텍스트를 생성하기 위해서는 __enter__() 와 __exit__()를 내부 함수로 갖는 클래스를 만든다. __enter__() 함수에서는 (파일을 열거나 데이터베이스 트랜잭션을 시작하는 것과 같은) 컨텍스트를 초기화하는 코드를 작성하고, __exit__() 함수에서는 어떤 예외를 처리하거나 단지 클린업 코드만을 수행한다. 예외의 경우에, __exit__()함수는 예외를 표현하기 위해 세개의 파라미터를 받는다. (Note: 자신만의 컨텍스트를 생성하는 것에 대한 세부사항을 알고 싶으면 Writing Context Managers in PEP 843을 참고하라.)
처음에는 컨텍스트라는게 별로 안 좋은 생각처럼 보일 수 있다. 이것은 (파일을 닫는 것과 같은) 특정한 치명적인 코드를 숨겨놓고 파일이 실제로 닫혔는지를 확실히 알 수 없게하는 것처럼 보인다. 그러나 이것은 여러분이 사용하는 라이브러리와 같은 경우다. 추상화는 특정한 행동을 숨기지만, 여러분은 그 라이브러리가 필요한 작업을 하고 있다는 것을 안다. 라이브러리는 작업을 가볍게 만든다. 컨텍스트가 코드를 단순화 시키는 것처럼 생각하라. 반면에 가비지 컬렉션과 같은 행위를 확보하는 것만큼 여러분이 스스로 해야할 기타 세부적인 사항에 주의를 기울여라.
몇몇 내장된 파이썬 모듈과 클래스들은 이제 컨텍스트 관리가 포함되어 있다. 이것을 사용하기 위해서는 새로운 with 키워드를 사용한다. 그러나 with를 사용하기에 앞서 with 기능을 사용가능케 하라:
from __future__ import with_statement
(2.6버전에서는 이렇게 시작해서는 안될 것이다.)
컨텍스트를 지원하는 이러한 내장 파이썬 객체들은 이제 컨텍스트 관리를 제공하기 위해 __enter__()와 __exit__() 함수를 필요로 한다. 이것은 클린업에 의하여 더욱 편해질 것이다. 다음 코드를 보라:
with open("/test.txt", "r") as f:
for line in f:
process(line)
with문을 사용함으로써 직접 파일을 닫는 것에 대해 걱정할 필요가 없어졌다. 코드가 그것을 해준다. 정말로 필자가 이 코드 뒤에 f의 값을 쓰려고 시도했더니 파일이 닫혀있다는 것을 보게 되었다.
>>> print f
필자 개인적으로는, 이와 같은 컨텍스트를 사용하는 것은 그런 코드를 작성할 때 생각의 전환이 약간 필요할 것이다. 그러나 결국에 가서는, 우리 모두가 보다 적은 버그를 가진 코드를 작성하는데 도움을 줄 것이다. 왜냐하면 파일을 닫는 것을 잊거나 다른 필요한 클린업 코드를 수행하는 것을 걱정할 필요가 없기 때문이다.
약간의 작은 언어 변경사항
다음은 언어로의 약간 더 변경된 사항이다.
- Dictionaries 와 missing keys. 만약 dict로부터 새 사전 클래스를 파생시키려면 키가 사전 내에 존재하지 않을 때 검색을 다루기 위해 __missing__(self, key) 함수를 정의할 수 있다.
- 문자열 클래스의 새로운 partition과 rpartition 메소드. 이들 함수는 특정한 부분 문자열에서 문자열을 분리할 수 있게 하는데, 분리자의 왼쪽으로의 부분 문자열과, 분리자 자신, 분리자 오른쪽으로의 부분 문자열을 담은 집합을 얻어낸다.
- startswith 와 endswith 에서의 요소집합(tuple). 문자열 메소드인 startswith와 endswith 메소드는 어떤 문자열이 주어진 부분 문자열로 시작되거나 끝나는지를 테스팅하기 위해 이미 존재하고 있다. 이전에는 단일 부분 문자열의 존재여부만 테스트 할 수 있었다. 2.5 버전에 와서는 주어진 부분 문자열의 집합의 원소 존재여부를 테스트하기 위해 요소집합을 줄 수 있다.
- Min과 max를 사용한 Key함수. 이제 각 함수의 차례를 평가하기 위해 min과 max 함수를 함수의 이름에 줄 수 있게 되었다. 예를 들어, 다음처럼 문자열의 순서를 결정해야 할 것이다.
def myord(astr):
try:
num = int(astr)
return num
except:
return len(astr)
그리고 나서 문자열의 리스트를 주고 함수로 최대값을 얻을 수 있다:
print max(["abc","100","a","xyz","1"], key=myord)
- 바이너리 표현 함수들. 파이썬 2.5는 이제 바이너리 표현에 유용한 두개의 내장 함수를 포함하게 되었다. any() 함수는 요소들 중 어느 것이라도 참이면 참 값을 반환한다. all() 함수는 모든 요소들이 참일때만 참 값을 반환한다. 다음은 any()를 활용한 몇 개의 예제 코드를 보여준다.
>>> a = 10
>>> b = 20
>>> any([a<5, b<5])
True
>>> any([a<50, b<50])
False
>>> any([a<50, b<5])
True
파이썬 2.5는 짧은 설명을 가진 몇 개의 소규모 변화를 더 포함하고 있다. 여기서 그것들을 다시 반복하기 보다는
Other Language Changes에서 논의하기로 한다:
- __index__ 메소드 지원
- 절대 경로와 상대 경로를 대비한 임포트의 지원
- 인터프리터에서의 새로운 quit() 함수
새롭거나 향상된 라이브러리들
코어 모듈들은 많은 변화가 있어보인다. 전체 세부사항은
New, Improved, and Removed Modules에서 볼 수 있다. 다음은 몇 가지를 요약한 것이다.
임시 공유 라이브러리와 DLL 호출
이번 파이썬 2.5에는 ctypes라는 좋은 패키지가 하나 생겼다. (이 패키지는 얼마간은 나돌았었지만, 이제 새로운 버전으로 파이썬의 일부로 포함되었다.) ctypes는 외부 공유 라이브러리를 로드할 수 있고, 로드 후에는 라이브러리 내의 함수를 호출할 수 있다. 다음은 필자가 윈도우에서 시스템 라이브러리인 USER32 내의 함수를 호출한 예이다:
>>> import ctypes
>>> libc = ctypes.CDLL("c:/windows/system32/user32.dll")
>>> print libc.GetDesktopWindow()
필자는 이 글에서 개인적인 의견은 삼가해 왔지만 이것은 말해야 할 것 같다. 이 모듈은 써드 파티(third-party) 라이브러리 내로 호출하는 코드를 작성하는 사람들을 위해 신이 주신 선물이라고.
ElementTree를 통해 XML로 작업하기
예전에는 XML 파일을 파싱하는 것은 악몽이었다. XML 파일을 생성하는 것은 약간더 쉬웠지만 많은 작업을 해주어야 했다. XML 사용이 점점 더 많아지고 발전해 감에 따라, 사람들은 (XML 자체는 변경하지 않은 채) XML을 관리하기 위한 더 나은 프로그래밍 패러다임을 발견해 왔다.
ElementTree 모듈은 XML 처리를 엄청나게 단순화 시켰다.
>>> from xml.etree import ElementTree as ET
>>> tree = ET.parse("test.xml")
>>> r = tree.getroot()
>>> r
>>> def trav(node, indent=0):
... for c in node.getchildren():
... print " "*indent, c.tag, ":", c.text
... trav(c, indent+1)
...
>>>
>>> trav(r)
header1 : abc
text1 : This is some
b : text
text1 : This is some more text
>>>
ElementTree내의 클래스들은 XML을 읽고 XML 계층구조를 탐색할 수 있게 한다. 필자가 사용한 이 예제 코드는 자식 노드들을 탐색해 내려가는 재귀적인 방법을 사용했다. 필자가 XML로 수많은 작업을 해본 결과, 이처럼 XML을 계층적으로 파싱하는 것이 선형적으로 접근하는 것보다 훨씬 유용하다는 것을 알았다.
간단한 SQL 데이터 저장을 위한 SQLite 지원
sqlite3 모듈은
SQLite 라이브러리에 대한 인터페이스이다. 이 라이브러리는 데이터 저장에 사용하는 임의의 단일 파일에 대한 SQL 접근을 제공하며, 필자가 알아본 바로는 거대한 외부 데이터 베이스 시스템의 도움없이 적은 양의 로컬 데이터를 저장하는데에 있어 매우 유용하다.
다음은 그 예이다:
import sqlite3
conn = sqlite3.connect("data.dat")
c = conn.cursor()
c.execute("""
create table members(
id int,
name varchar,
login timestamp
)
""")
c.execute("""
insert into members
values (1,"jeff","2006-10-01")
""")
c.execute("""
insert into members
values (2,"angie","2006-10-02")
""")
c.execute("""
insert into members
values (3,"dylan","2006-10-03")
""")
res = c.execute("select * from members")
for row in res:
print row
이 코드는 데이터베이스(단순한 파일인 data.dat)에 접속하고 나서, 표준 SQL CREATE TABLE 문법을 사용하여 데이터 베이스 내에 새로운 테이블을 생성한다. 그리고 다시 표준 SQL 문법을 사용하여 데이터를 삽입하고 그 후 마지막으로 다시 SQL을 사용하여 테이블에서 데이터를 선택한다. 그리고 선택된 데이터들에 대해 반복문을 사용한다.
이 모듈은 마땅히 큰 데이터베이스 시스템을 사용할 이유가 그리 충분하지 않을 때 특별히 유용하다. 그러나 본질적으로 관계적(relational)이고 간단한 데이터 타입 이상을 필요로 한다.
요약
파이썬 2.5는 많은 반가운 변화들이 생겼다. 필자는 개인적으로 XML 처리를 위한 ElementTree클래스와 데이터 저장을 위한 SQLite클래스들을 많이 사용하게 될 것 같다.
언어 자체의 변화, 특히 제네레이터와 컨텍스트는 좀 더 강건한 코드를 작성하는데 도움이 될 것 같으며, 어떻게 하는가에 대한 강조를 버리고 무엇을 할 것인가에 대해 더욱 초점을 맞출 수 있을 것이다.
2.5버전으로의 변화들을 살펴볼 때, 많은 변경사항들이 파이썬 3.0이 나오면 등장하게 될 것들의 사전 포석임을 기억하라. 지금 그 변화들에 적응하기 시작한다면 코드를 이전하고 변경할 것이 적어지므로 파이썬 3.0을 준비하는데 더욱 유리할 것이다. 필자는 여러분들이 이러한 변화들을 연구하고 사용하길 권장한다. 그리고 가장 중요한 것은 즐기라는 것이다!
Jeff Cogswell 는 신시내티 근처에 살며 15년이 넘게 소프트웨어 엔지니어로 근무해오고 있다.