database.sarang.net
UserID
Passwd
Database
ㆍDBMS
MySQL
PostgreSQL
Firebird
Oracle
Informix
Sybase
MS-SQL
DB2
Cache
CUBRID
LDAP
ALTIBASE
Tibero
DB 문서들
스터디
Community
공지사항
자유게시판
구인|구직
DSN 갤러리
도움주신분들
Admin
운영게시판
최근게시물
DBMS Tutorials 492 게시물 읽기
 News | Q&A | Columns | Tutorials | Devel | Files | Links
No. 492
파이썬에서 데이터베이스 사용하기
작성자
정재익(advance)
작성일
2002-08-05 22:22
조회수
12,252

파이썬에서 데이터베이스 사용하기

 

CGI 프로그래밍에서 마지막으로 배워야 할 부분이 어떻게 하면 데이터베이스 질의언어 (SQL)를 파이썬에서 사용할 수 있을까 하는 것이다. 파이썬은 데이테베이스와 작업을 하기위하여 표준 API(Application Programming Interface)를 제공한다. 이 인터페이스는 제공되는 모든 데이터베이스에서 동일하게 사용할 수 있다. 따라서 여러분은 프로그램을 수정하지 않고도 어떠한 데이터베이스를 사용할 수 있다(이론적으로는).

 

현재 Python DBI (Database Interface) 대부분의 일반적인 데이터베이스를 지원한다 - Gadfly, mSQL, MySQL, Oracle, PostgreSQL, Informix, Interbase, Sybase, Solid

 

표준적인 인터페이스를 지원하지만 다른 데이터베이스를 사용하기 위해서는 각 DB에 맞는 모듈이 있어야 하는 것을 잊지는 말아라(노파심에서 한마디).

 

더욱 자세한 정보를 원한다면 the Database SIG (Special Interest Group)에 가보라.

 

여기서는 MySQL을 이용한 아주 단순한 읽기 질의를 다룬다. 처음에 해야 할 일은 모듈을 import하는 것이다.

 

import MySQLdbMySQL DBI 모듈을 불렀으면, 데이터베이스를 연결함으로 초기화한다. 이 연결을 위해서 클래스 인스턴스를 생성해야 하는데 형식은 다음과 같다.

 

MySQLdb.connect(host, user, passwd, db, port, unix_socket, client_flag)

 

이 인터페이스는 키워드 인수를 통해서 필요한 값만 전달한다.

 

host - hostname (NULL : default)

user - username (NULL)

passwd - password (no password)

db - database name (NULL)

port - integer, TCP/IP port

unix_socket - TCP를 사용할 unix소켓의 위치

client_flag - integer, 필요할 경우 사용하기 위한 flag (0)사용자를 gslee 암호를 secretpassword라 할 때 localhost에서 guestbook이라는 데이터베이스를 사용하기 위한 초기화 예는 다음과 같다.

 

--------------------------------------------------------------------------------

import MySQLdb

connection = MySQLdb.connect(user='gslee', passwd='secretpassword', db='guestbook')

cursor = connection.cursor() # 커서 객체를 얻어온다.

.....

cursor.close() #사용이 종료되면 닫아준다. (직접 안하면 자동으로 닫아진다)

--------------------------------------------------------------------------------

 

마지막 문장은 커서(cursor)라고 불리는 것을 리턴했다. 이 객체의 이름을 '커서'라고 하는데, 모든 데이터베이스의 액션은 커서를 통해서 이루어진다. 프로그램과 데이터베이스를 연결 해 주는 것이 커서의 역할이라 할 수 있다. 커서 객체는 execute()와 fetchall()과 같은 몇 개의 메써드를 가지고 있다. execute()는 실제적으로 SQL 문을 수행하기 위해 사용되며 fetchall()은 execute()의 결과를 터플 형식으로 얻기 위해서 사용된다. 각 터플은 데이터베이스의 행(레코드)에 대응된다.

 

커서가 있다면, cursor.execute(statement)와 같은 형식으로 데이터베이스가 지원하는 어떠한 SQL 문도 수행할 수 있다. 전체 레코드를 얻는 간단한 예를 아래에 보인다.

 

--------------------------------------------------------------------------------

#모든 엔트리를 얻는다.
myquery = "SELECT * FROM gbook ORDER BY stamp"
cursor.execute(myquery) #질의 수행
Result = cursor.fetchall() # 결과 가져오기
total = len(Result) # 결과 레코드 수 얻기
 
entries = []
 
if total < 1:
    print 'No guest book entries!'
else:
    for record in range(total):
        entry = {} # 공 사전
        entry['gid'] = Result[record][0] # guestbook ID
        entry['stamp'] = Result[record][1] # time stamp
        entry['name'] = Result[record][2] # ...
        entry['email'] = Result[record][3]
        entries.append(entry) # 리스트에 정보 추가
 
for entry in entries:
    print entry['name'] + '  email:' + entry['email'] + '...'
 
-------------------------------------------------------------------------------- 

결과가 Result에 저장되며, 질의 결과로 넘어온 전체 레코드 수는 total에 저장된다. Result에 저장된 결과는 터플의 리스트 형식이므로 각 필드에 맞추어서 정보를 얻기 위해서는 필드 이름과 위치 정보를 미리 알고 있어야 한다. 0번째 필드는 guestbook ID로 사용되고 있는 것을 아는 상태에서 위와 같이 정보를 추출 할 수 있다. 이와 같은 사전 정보 없이 각 필드의 이름과 데이터 형, 크기등을 알고 싶다면 execute를 수행한 후, description 특성을 이용하면 정보를 얻을 수 있다. 이에 관한 자세한 사항은 Python Database API 2.0 문서를 참고하기 바란다.

 

for문에서 각 레코드 단위로 정보가 사전 형식으로 entry에 저장되고, 그 사전은 다시 entries 리스트에 추가된다.

 

마지막 for문은 저장된 정보를 출력한다.

 

데이터베이스를 다루는 것에 대해서 충분하게 다루지는 못했지만 CGI와 연결해서 다룰 만큼의 기초는 충분하다고 생각된다. 앞으로 문서가 갱신된다면 좀더 자세하게 데이터베이스를 다루는 루틴을 소개하겠다.

 

Python Database API 2.0 커서 객체에 대해서 좀 더 자세히

 

이 API는 데이터베이스를 사용하는 유사한 파이썬 모듈간의 호환성을 유지하기 위해서 정의되었다. 이것을 만들고 사용함으로 다른 데이터베이스에 변경없이 쉽게 적용 가능한 이해하기 쉬운 코드를 생성할 수 있다. (이것은 커다란 장점이다!!)

 

커서 객체

 

커서 객체는 질의를 수행하고 실행된 결과를 가져오기 위해서 사용된다. 커서 객체를 만드는 방법은 앞절에서 기술하였지만 다음과 같이 connection 객체로부터 얻어올 수 있다.

 

import MySQLdb

connection = MySQLdb.connect(user='guest', db='test')

cursor = connection.cursor() # 커서 객체를 얻어온다.일단 커서 객체를 받았으면 execute 메써드를 이용하여 질의를 수행할 수 있다.

 

cursor.execute('select * from pet')아무 메시지 없이 다름 프롬프트가 나오면 성공한 것이다. 질의 결과로 얻어진 각 필드의 특성을 알고 싶으면 description 특성(attribute)을 이용하라.

 

print cursor.description

 

(('name', 253, 8, 20, 20, 0, 1), ('owner', 253, 6, 20, 20, 0, 1),

('species', 253, 7, 20, 20, 0, 1), ('sex', 254, 1, 1, 1, 0, 1),

('birth', 10, 10, 10, 10, 0, 1), ('death', 10, 10, 10, 10, 0, 1))

 

결과는 7개 시퀀스의 시퀀스(터플)인데, 7개 값의 의미는 다음과 같다.

 

(name, type_code, display_size, internal_size, precision, scale, null_ok)

 

(필드명, 데이터형_코드, 표시크기, 내부크기, 정확도, 비율, null가능여부)('name', 253, 8, 20, 20, 0, 1)을 예를 들어 설명하면 다음과 같다.

 

필드이름('name')-name, 데이터형(253)-VARCHAR, 표시크기(8)-8,

내부크기(20)-20 (VARCHAR(20)으로 선언되었다.),

정확도-20, 비율-0(스트링에서 별 의미 없음), null가능(1)-Yesdescription은 만일 execute()를 호출한 적이 없거나 검색 결과 행을 가지고 있지 않다면 None값을 갖는다.

 

rowcount는 검색(select) 결과 레코드의 수 혹은 (update, insert등으로) 변경된 레코드의 수를 알려준다.

 

print cursor.rowcount

 

11L질의 결과를 가져오기 위해서는 fetchone(), fetchmany(), 혹은 fetchall() 메써드를 사용할 수 있다.

 

res = cursor.fetchone() # 결과 한 개 가져오기

res = cursor.fetchall() # 결과 모두 가져오기

res = cursor.fetchmany(10) # 결과 10개 가져오기이름에서 알 수 있듯이 fetchone()은 하나의 레코드를 터플로 리턴하며, fetchall()은 모든 레코드를 터플의 리스트로 리턴한다.

 

fetchmany(n)은 n개 만큼의 레코드를 가져온다. 만일 숫자가 지정되지 않으면 (기본값을 사용하면) cursor.arraysize 만큼의 레코드를 가져온다. 만일 충분하지 않은 레코드가 남아있다면 그 남아있는 레코드가 넘어온다. 가능한 한 일정한 수의 레코드를 요구하는 것이 시스템 성능에 도움을 준다.

 

만일 execute()에서 아무 결과가 없었다면 예외가 발생한다.

 

res = cursor.fetchall()의 질의 결과는 터플의 리스트 형태로 저장된다. 하나의 터플은 하나의 행(레코드)를 나타낸다.

 

res = cursor.fetchall() # 결과 모두 가져오기

print res

 

[('Puffball', 'Diane', 'hamster', 'f', '1999-03-30', None), ('buffy', 'harold',

'dog', 'f', '1990-05-13', '0000-00-00'), ('Claws', 'Gwen', 'cat', 'm', '1994-03-

17', '0000-00-00'), ('whistler', 'gwen', 'bird', 'n', '1997-12-09', '0000-00-00'

), ('Fluffy', 'Harold', 'cat', 'f', '1993-02-04', None), ('Chirpy', 'Gwen', 'bir

d', 'f', '1998-09-11', None), ('Bowser', 'Diane', 'dog', 'm', '1989-08-31', '199

5-07-29'), ('fang', 'benny', 'dog', 'm', '1998-08-27', '0000-00-00'), ('slim', '

benny', 'snake', 'm', '1996-04-29', '0000-00-00'), ('fang', 'benny', 'dog', 'f',

'1998-09-22', '0000-00-00'), ('slim', 'benny', 'snak', 'm', '1996-04-29', '0000

-00-00')]

 

좀더 품위 있게 정보를 출력하려면 다음과 같은 코드를 이용할 수 있다.

 

res = cursor.fetchall() # 결과 모두 가져오기

print "%-10s %-8s %-8s %1s %11s %11s" % ('name', 'owner', 'species', 's', 'birth', 'death')

print

for record in res:

print "%-10s %-8s %-8s %1s %11s %11s" % record

 

 
name       owner    species  s       birth       death 
 
Puffball   Diane    hamster  f  1999-03-30        None
buffy      harold   dog      f  1990-05-13  0000-00-00
Claws      Gwen     cat      m  1994-03-17  0000-00-00
whistler   gwen     bird     n  1997-12-09  0000-00-00
Fluffy     Harold   cat      f  1993-02-04        None
Chirpy     Gwen     bird     f  1998-09-11        None
Bowser     Diane    dog      m  1989-08-31  1995-07-29
fang       benny    dog      m  1998-08-27  0000-00-00
slim       benny    snake    m  1996-04-29  0000-00-00
fang       benny    dog      f  1998-09-22  0000-00-00
slim       benny    snak     m  1996-04-29  0000-00-00                         

 

또는 다음과 같이 하나씩 출력할 수도 있다. 위와 같은 출력을 얻을 것이다.

print "%-10s %-8s %-8s %1s %11s %11s" % ('name', 'owner', 'species', 's', 'birth', 'death')
print
while 1:
    record = cursor.fetchone() # 결과 하나 가져오기
    if record == None: break   # 없으면 빠져나감
    print "%-10s %-8s %-8s %1s %11s %11s" % record
[Top]
No.
제목
작성자
작성일
조회
498Draft Specs of SQL 3 (PDF)
정재익
2002-08-08
4340
497Database Powered LaTeX Form Letters
정재익
2002-08-08
4180
494Design Transactions and Serializability
정재익
2002-08-06
4240
492파이썬에서 데이터베이스 사용하기
정재익
2002-08-05
12252
456ADO Connection Samples
정재익
2002-07-20
71979
455APM+Zend 설치하기
정재익
2002-07-18
4286
454Partitioned Table의 Index
정재익
2002-07-16
8905
Valid XHTML 1.0!
All about the DATABASE... Copyleft 1999-2024 DSN, All rights reserved.
작업시간: 0.028초, 이곳 서비스는
	PostgreSQL v16.2로 자료를 관리합니다