Following system colour scheme Selected dark colour scheme Selected light colour scheme

Python 개선 제안 한국어 번역

PEP 249 – Python 데이터베이스 API 명세 v2.0

Author:
Marc-André Lemburg <mal at lemburg.com>
Discussions-To:
Db-SIG list
Status:
Final
Type:
Informational
Created:
12-Apr-1999
Post-History:

Replaces:
248

Table of Contents

번역·라이선스 안내

이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판

소개

이 API는 데이터베이스에 접근하는 데 사용되는 Python 모듈 간의 유사성을 촉진하기 위해 정의되었습니다. 이를 통해 더 쉽게 이해할 수 있는 모듈, 데이터베이스 간에 더 이식성이 높은 코드, 그리고 Python으로부터의 데이터베이스 연결성 확장이라는 일관성을 달성하고자 합니다.

이 명세에 대한 의견과 질문은 SIG for Database Interfacing with Python으로 보내주십시오.

Python을 이용한 데이터베이스 인터페이싱과 사용 가능한 패키지에 대한 더 자세한 정보는 Database Topic Guide를 참조하십시오.

이 문서는 Python 데이터베이스 API 명세 2.0과 일반적인 선택적 확장 기능 모음을 설명합니다. 이전 버전인 1.0 버전은 PEP 248에서 참조용으로 여전히 제공됩니다. 패키지 작성자는 새로운 인터페이스의 기반으로 이 버전의 명세를 사용할 것을 권장받습니다.

모듈 인터페이스

생성자

데이터베이스에 대한 접근은 연결 객체를 통해 제공됩니다. 모듈은 이를 위해 다음 생성자를 제공해야 합니다:

connect( parameters… )
데이터베이스에 대한 연결을 생성하기 위한 생성자입니다.

Connection 객체를 반환합니다. 데이터베이스에 따라 달라지는 여러 매개변수를 받습니다. [1]

전역 변수

이 모듈 전역 변수들은 반드시 정의되어야 합니다:

apilevel
지원되는 DB API 레벨을 나타내는 문자열 상수입니다.

현재는 문자열 “1.0”과 “2.0”만 허용됩니다. 지정되지 않으면, DB-API 1.0 레벨 인터페이스로 가정해야 합니다.

threadsafety
인터페이스가 지원하는 스레드 안전성 수준을 나타내는 정수 상수입니다. 가능한 값은 다음과 같습니다:
threadsafety 의미
0 스레드가 모듈을 공유할 수 없습니다.
1 스레드는 모듈을 공유할 수 있지만, 커넥션은 공유할 수 없습니다.
2 스레드는 모듈과 커넥션을 공유할 수 있습니다.
3 스레드는 모듈, 커넥션, 커서를 공유할 수 있습니다.

위 맥락에서 공유란 두 스레드가 자원 잠금을 구현하기 위해 뮤텍스 세마포어로 감싸지 않고도 해당 자원을 사용할 수 있다는 의미입니다. 뮤텍스로 접근을 관리한다고 해서 외부 자원을 항상 스레드 안전하게 만들 수 있는 것은 아니라는 점에 유의하십시오. 해당 자원이 제어할 수 없는 전역 변수나 다른 외부 소스에 의존할 수 있기 때문입니다.

paramstyle
인터페이스가 요구하는 매개변수 마커 형식의 종류를 나타내는 문자열 상수입니다. 가능한 값은 다음과 같습니다[2]:
paramstyle 의미
qmark 물음표 스타일입니다. 예: ...WHERE name=?
numeric 숫자 기반의 위치 스타일입니다. 예: ...WHERE name=:1
named Named 스타일, 예: ...WHERE name=:name
format ANSI C printf 형식 코드, 예: ...WHERE name=%s
pyformat Python 확장 형식 코드, 예: ...WHERE name=%(name)s

예외

이 모듈은 이러한 예외나 그 서브클래스를 통해 모든 오류 정보를 사용할 수 있도록 해야 합니다:

Warning
삽입 중 데이터 잘림 등과 같은 중요한 경고에 대해 발생하는 예외입니다. 이는 Python Exception 클래스 [10] [11]의 서브클래스여야 합니다.
Error
다른 모든 오류 예외의 베이스 클래스가 되는 예외입니다. 단일 except 문 하나로 모든 오류를 포착하는 데 이를 사용할 수 있습니다. 경고는 오류로 간주되지 않으므로 이 클래스를 베이스로 사용해서는 안 됩니다. Python Exception 클래스 [10]의 서브클래스여야 합니다.
InterfaceError
데이터베이스 자체가 아니라 데이터베이스 인터페이스와 관련된 오류에 대해 발생하는 예외입니다. Error의 서브클래스여야 합니다.
DatabaseError
데이터베이스와 관련된 오류에 대해 발생하는 예외입니다. Error의 서브클래스여야 합니다.
DataError
0으로 나누기, 숫자 값 범위 초과 등 처리된 데이터의 문제로 인한 오류에 대해 발생하는 예외입니다. DatabaseError의 서브클래스여야 합니다.
OperationalError
예기치 않은 연결 끊김 발생, 데이터 소스 이름을 찾을 수 없음, 트랜잭션을 처리할 수 없음, 처리 중 메모리 할당 오류 발생 등 프로그래머가 반드시 제어할 수 있는 것은 아닌 데이터베이스의 동작과 관련된 오류에 대해 발생하는 예외입니다. DatabaseError의 서브클래스여야 합니다.
IntegrityError
외래 키 검사 실패 등 데이터베이스의 관계형 무결성이 영향을 받을 때 발생하는 예외입니다. DatabaseError의 서브클래스여야 합니다.
InternalError
커서가 더 이상 유효하지 않음, 트랜잭션이 동기화되지 않음 등 데이터베이스가 내부 오류를 만났을 때 발생하는 예외입니다. DatabaseError의 서브클래스여야 합니다.
ProgrammingError
테이블을 찾을 수 없거나 이미 존재함, SQL 문의 구문 오류, 지정된 매개변수 개수 오류 등 프로그래밍 오류에 대해 발생하는 예외입니다. DatabaseError의 서브클래스여야 합니다.
NotSupportedError
데이터베이스에서 지원하지 않는 메서드나 데이터베이스 API가 사용된 경우 발생하는 예외입니다. 예를 들어 트랜잭션을 지원하지 않거나 트랜잭션이 꺼져 있는 연결에서 .rollback()을 요청하는 경우입니다. DatabaseError의 서브클래스여야 합니다.

다음은 예외 상속 구조입니다 [10] [11]:

Exception
|__Warning
|__Error
   |__InterfaceError
   |__DatabaseError
      |__DataError
      |__OperationalError
      |__IntegrityError
      |__InternalError
      |__ProgrammingError
      |__NotSupportedError

Note

이러한 예외의 값은 정의되어 있지 않습니다. 그러나 사용자에게 무엇이 잘못되었는지 상당히 잘 알려줄 수 있어야 합니다.

연결 객체

연결 객체는 다음 메서드에 응답해야 합니다.

연결 메서드

.close()
지금 즉시 연결을 닫습니다(.__del__()이 호출될 때가 아니라).

이 시점부터 연결은 사용할 수 없게 되며, 연결로 어떤 작업이든 시도하면 Error (또는 서브클래스) 예외가 발생합니다. 연결을 사용하려는 모든 커서 객체에도 마찬가지로 적용됩니다. 변경 사항을 커밋하지 않고 연결을 닫으면 암묵적인 롤백이 수행된다는 점에 유의하십시오.

.commit()
데이터베이스에 대기 중인 트랜잭션을 커밋합니다.

데이터베이스가 자동 커밋 기능을 지원하는 경우, 이 기능은 처음에 꺼져 있어야 함에 유의하십시오. 이를 다시 켤 수 있는 인터페이스 메서드가 제공될 수 있습니다.

트랜잭션을 지원하지 않는 데이터베이스 모듈은 이 메서드를 아무 동작도 하지 않도록 구현해야 합니다.

.rollback()
이 메서드는 모든 데이터베이스가 트랜잭션 지원을 제공하는 것은 아니므로 선택 사항입니다. [3]

데이터베이스가 트랜잭션을 지원하는 경우, 이 메서드는 데이터베이스가 대기 중인 트랜잭션의 시작 지점으로 롤백하게 합니다. 변경 사항을 커밋하지 않고 연결을 닫으면 암묵적인 롤백이 수행됩니다.

.cursor()
이 연결을 사용하여 새 Cursor 객체를 반환합니다.

데이터베이스가 직접적인 커서 개념을 제공하지 않는 경우, 모듈은 이 명세에서 필요로 하는 정도까지 다른 수단을 사용하여 커서를 에뮬레이션해야 합니다. [4]

커서 객체

이 객체들은 데이터베이스 커서를 나타내며, 페치 연산의 컨텍스트를 관리하는 데 사용됩니다. 동일한 연결에서 생성된 커서들은 격리되지 않으므로, 한 커서가 데이터베이스에 가한 변경 사항은 다른 커서들에게 즉시 보입니다. 서로 다른 연결에서 생성된 커서는 트랜잭션 지원이 구현된 방식에 따라 격리될 수도 있고 그렇지 않을 수도 있습니다(연결의 .rollback()과 .commit() 메서드도 참조하십시오).

커서 객체는 다음 메서드와 속성에 응답해야 합니다.

커서 속성

.description
이 읽기 전용 속성은 7개 항목의 시퀀스로 구성된 시퀀스입니다.

이 시퀀스들 각각은 하나의 결과 열을 설명하는 정보를 담고 있습니다:

  • name
  • type_code
  • display_size
  • internal_size
  • precision
  • scale
  • null_ok

처음 두 항목(nametype_code)은 필수이며, 나머지 다섯 개는 선택적이고 의미 있는 값을 제공할 수 없는 경우 None으로 설정됩니다.

이 속성은 행을 반환하지 않는 연산의 경우 또는 커서에 아직 .execute*() 메서드를 통해 연산이 호출되지 않은 경우 None이 됩니다.

type_code는 아래 절에 명시된 Type Objects와 비교하여 해석할 수 있습니다.

.rowcount
이 읽기 전용 속성은 마지막 .execute*()가 생성한(SELECT와 같은 DQL 문의 경우) 또는 영향을 미친(UPDATEINSERT와 같은 DML 문의 경우) 행 수를 지정합니다. [9]

이 속성은 커서에 .execute*()가 수행된 적이 없거나 마지막 연산의 rowcount를 인터페이스가 판별할 수 없는 경우 -1입니다. [7]

Note

DB API 명세의 향후 버전에서는 후자의 경우를 재정의하여 객체가 -1 대신 None을 반환하도록 할 수 있습니다.

커서 메서드

.callproc( procname [, parameters ] )
(이 메서드는 모든 데이터베이스가 저장 프로시저를 제공하지는 않기 때문에 선택 사항입니다. [3])

지정된 이름으로 데이터베이스 저장 프로시저를 호출합니다. 매개변수 시퀀스에는 프로시저가 기대하는 각 인자에 대해 하나의 항목이 포함되어야 합니다. 호출 결과는 입력 시퀀스를 수정한 복사본으로 반환됩니다. 입력 매개변수는 그대로 유지되며, 출력 및 입출력 매개변수는 새로운 값으로 대체될 수 있습니다.

프로시저는 결과 집합을 출력으로 제공할 수도 있습니다. 이 경우 표준 .fetch*() 메서드를 통해 사용할 수 있어야 합니다.

.close()
__del__이 호출될 때가 아니라 지금 즉시 커서를 닫습니다.

이 시점 이후로 커서는 사용할 수 없게 되며, 커서에 대해 어떤 작업이라도 시도하면 Error (또는 그 서브클래스) 예외가 발생합니다.

.execute(operation [, parameters])
데이터베이스 작업(쿼리 또는 명령)을 준비하고 실행합니다.

매개변수는 시퀀스 또는 매핑으로 제공될 수 있으며, 연산 내의 변수에 바인딩됩니다. 변수는 데이터베이스별 표기법으로 지정됩니다(자세한 내용은 모듈의 paramstyle 속성을 참조하십시오). [5]

커서는 연산에 대한 참조를 유지합니다. 동일한 연산 객체가 다시 전달되면, 커서는 자신의 동작을 최적화할 수 있습니다. 이는 동일한 연산이 사용되지만 서로 다른 매개변수가 (여러 번) 바인딩되는 알고리즘에서 가장 효과적입니다.

연산을 재사용할 때 최대의 효율을 얻으려면, .setinputsizes() 메서드를 사용하여 매개변수 타입과 크기를 미리 지정하는 것이 가장 좋습니다. 매개변수가 미리 정의된 정보와 일치하지 않아도 무방하며, 이 경우 구현체는 이를 보완해야 하고, 그 과정에서 효율성 손실이 발생할 수 있습니다.

매개변수는 예를 들어 단일 연산으로 여러 행을 삽입하기 위해 튜플의 리스트로 지정될 수도 있지만, 이러한 사용 방식은 폐지되었으며 대신 .executemany()를 사용해야 합니다.

반환값은 정의되어 있지 않습니다.

.executemany( operation, seq_of_parameters )
데이터베이스 연산(쿼리 또는 명령)을 준비한 다음, 시퀀스 seq_of_parameters에서 찾은 모든 매개변수 시퀀스 또는 매핑에 대해 이를 실행합니다.

모듈은 이 메서드를 .execute() 메서드를 여러 번 호출하는 방식으로 구현하거나, 배열 연산을 사용하여 데이터베이스가 시퀀스 전체를 한 번의 호출로 처리하도록 하는 방식으로 구현해도 무방합니다.

하나 이상의 결과 집합을 생성하는 연산에 대해 이 메서드를 사용하는 것은 정의되지 않은 동작에 해당하며, 구현체는 연산 호출로 인해 결과 집합이 생성되었음을 감지했을 때 예외를 발생시키는 것이 허용됩니다(단, 필수는 아닙니다).

.execute()에 대한 것과 동일한 설명이 이 메서드에도 그대로 적용됩니다.

반환값은 정의되어 있지 않습니다.

.fetchone()
쿼리 결과 집합의 다음 행을 가져와 단일 시퀀스를 반환하거나, 더 이상 사용할 수 있는 데이터가 없으면 None을 반환합니다. [6]

이전에 이루어진 .execute*() 호출이 결과 집합을 생성하지 않았거나 아직 호출이 이루어지지 않은 경우 Error (또는 서브클래스) 예외가 발생합니다.

.fetchmany([size=cursor.arraysize])
쿼리 결과의 다음 행 집합을 가져와 시퀀스의 시퀀스(예: 튜플의 리스트)로 반환합니다. 더 이상 사용할 수 있는 행이 없으면 빈 시퀀스가 반환됩니다.

호출당 가져올 행의 수는 매개변수로 지정합니다. 매개변수가 주어지지 않으면 커서의 arraysize가 가져올 행의 수를 결정합니다. 이 메서드는 size 매개변수로 지정된 만큼의 행을 가져오려고 시도해야 합니다. 지정된 수의 행을 사용할 수 없어 이것이 불가능한 경우, 더 적은 수의 행이 반환될 수 있습니다.

이전에 이루어진 .execute*() 호출이 결과 집합을 생성하지 않았거나 아직 호출이 이루어지지 않은 경우 Error (또는 서브클래스) 예외가 발생합니다.

size 매개변수와 관련하여 성능상 고려할 사항이 있다는 점에 유의하십시오. 최적의 성능을 위해서는 일반적으로 .arraysize 속성을 사용하는 것이 가장 좋습니다. size 매개변수를 사용하는 경우, 한 .fetchmany() 호출에서 다음 호출까지 동일한 값을 유지하는 것이 가장 좋습니다.

.fetchall()
쿼리 결과의 모든(남은) 행을 가져와 시퀀스의 시퀀스(예: 튜플의 리스트)로 반환합니다. 커서의 arraysize 속성이 이 작업의 성능에 영향을 줄 수 있다는 점에 유의하십시오.

이전 .execute*() 호출이 어떠한 결과 집합도 생성하지 않았거나 아직 호출이 이루어지지 않은 경우, Error (또는 서브클래스) 예외가 발생합니다.

.nextset()
(이 메서드는 모든 데이터베이스가 다중 결과 집합을 지원하지는 않기 때문에 선택적입니다. [3])

이 메서드는 커서가 다음 사용 가능한 집합으로 건너뛰게 하며, 현재 집합의 남은 행은 모두 버립니다.

더 이상 집합이 없으면, 이 메서드는 None을 반환합니다. 그렇지 않으면 참 값을 반환하며, 이후 .fetch*() 메서드 호출은 다음 결과 집합의 행을 반환합니다.

이전 .execute*() 호출이 어떠한 결과 집합도 생성하지 않았거나 아직 호출이 이루어지지 않은 경우, Error (또는 서브클래스) 예외가 발생합니다.

.arraysize
이 읽기/쓰기 속성은 .fetchmany()로 한 번에 가져올 행 수를 지정합니다. 기본값은 1이며, 이는 한 번에 한 행씩 가져온다는 의미입니다.

구현체는 .fetchmany() 메서드와 관련하여 이 값을 준수해야 하지만, 데이터베이스와는 한 번에 한 행씩 상호작용해도 무방합니다. 이는 .executemany()의 구현에도 사용될 수 있습니다.

.setinputsizes(sizes)
이는 연산의 매개변수를 위한 메모리 영역을 미리 정의하기 위해 .execute*() 호출 전에 사용할 수 있습니다.

sizes는 시퀀스로 지정되며, 각 입력 매개변수당 하나의 항목을 갖습니다. 항목은 사용될 입력에 대응하는 Type Object여야 하며, 또는 문자열 매개변수의 최대 길이를 지정하는 정수여야 합니다. 항목이 None이면, 해당 열에 대해 미리 정의된 메모리 영역이 예약되지 않습니다(이는 큰 입력에 대해 미리 정의된 영역을 피하는 데 유용합니다).

이 메서드는 .execute*() 메서드가 호출되기 전에 사용됩니다.

구현은 이 메서드가 아무 일도 하지 않도록 자유롭게 만들 수 있으며, 사용자는 이를 사용하지 않아도 됩니다.

.setoutputsize(size [, column])
큰 열(예: LONGs, BLOBs 등)을 페치할 때 사용할 열 버퍼 크기를 설정합니다. 열은 결과 시퀀스에 대한 인덱스로 지정됩니다. 열을 지정하지 않으면 커서의 모든 큰 열에 대해 기본 크기가 설정됩니다.

이 메서드는 .execute*() 메서드가 호출되기 전에 사용됩니다.

구현은 이 메서드가 아무 일도 하지 않도록 자유롭게 만들 수 있으며, 사용자는 이를 사용하지 않아도 됩니다.

Type Objects and Constructors

많은 데이터베이스는 연산의 입력 매개변수에 바인딩하기 위해 입력이 특정 형식이어야 합니다. 예를 들어, 입력이 DATE 열에 대한 것이라면, 특정 문자열 형식으로 데이터베이스에 바인딩되어야 합니다. “Row ID” 열이나 큰 바이너리 항목(예: blob 또는 RAW 열)에도 비슷한 문제가 있습니다. .execute*() 메서드의 매개변수에 타입이 없기 때문에, 이는 Python에 문제를 일으킵니다. 데이터베이스 모듈이 Python 문자열 객체를 보면, 이를 단순 CHAR 열로 바인딩해야 할지, 원시 BINARY 항목으로 바인딩해야 할지, 아니면 DATE로 바인딩해야 할지 알 수 없습니다.

이 문제를 극복하기 위해, 모듈은 특수한 값을 담을 수 있는 객체를 생성하는, 아래에 정의된 생성자를 제공해야 합니다. 커서 메서드에 전달되면, 모듈은 입력 매개변수의 올바른 타입을 감지하여 그에 맞게 바인딩할 수 있습니다.

Cursor 객체의 description 속성은 쿼리의 각 결과 열에 대한 정보를 반환합니다. type_code는 아래에 정의된 Type Objects 중 하나와 비교하여 같아야 합니다. Type Objects는 두 개 이상의 type code와 같을 수 있습니다(예를 들어, DATETIME은 date, time, timestamp 열의 type code와 같을 수 있습니다; 자세한 내용은 아래 Implementation Hints를 참조하십시오).

이 모듈은 다음과 같은 생성자와 싱글턴을 내보냅니다:

Date(year, month, day)
이 함수는 날짜 값을 담는 객체를 생성합니다.
Time(hour, minute, second)
이 함수는 시간 값을 담는 객체를 생성합니다.
Timestamp(year, month, day, hour, minute, second)
이 함수는 타임스탬프 값을 담는 객체를 생성합니다.
DateFromTicks(ticks)
이 함수는 주어진 ticks 값(에포크 이후 경과한 초 수; 자세한 내용은 표준 Python time 모듈의 문서를 참조하십시오)으로부터 날짜 값을 담는 객체를 생성합니다.
TimeFromTicks(ticks)
이 함수는 주어진 ticks 값(에포크 이후 경과한 초 수; 자세한 내용은 표준 Python time 모듈의 문서를 참조하십시오)으로부터 시간 값을 담는 객체를 생성합니다.
TimestampFromTicks(ticks)
이 함수는 주어진 ticks 값(에포크 이후 경과한 초 수; 자세한 내용은 표준 Python time 모듈의 문서를 참조하십시오)으로부터 타임스탬프 값을 담는 객체를 생성합니다.
Binary(string)
이 함수는 바이너리(긴) 문자열 값을 담을 수 있는 객체를 생성합니다.
STRING 타입
이 타입 객체는 데이터베이스에서 CHAR와 같은 문자열 기반 컬럼을 기술하는 데 사용됩니다.
BINARY 타입
이 타입 객체는 데이터베이스에서 LONG, RAW, BLOBs와 같은 (긴) 바이너리 컬럼을 기술하는 데 사용됩니다.
NUMBER 타입
이 타입 객체는 데이터베이스에서 숫자형 컬럼을 기술하는 데 사용됩니다.
DATETIME 타입
이 타입 객체는 데이터베이스의 날짜/시간 열을 기술하는 데 사용됩니다.
ROWID타입
이 타입 객체는 데이터베이스의 “Row ID” 열을 기술하는 데 사용됩니다.

SQL NULL 값은 입력과 출력 모두에서 파이썬 None 싱글턴으로 표현됩니다.

Note

데이터베이스 인터페이싱에 유닉스 틱을 사용하면 그것이 다루는 날짜 범위가 제한적이기 때문에 문제가 발생할 수 있습니다.

모듈 작성자를 위한 구현 힌트

  • 날짜/시간 객체는 Python datetime module 객체(파이썬 2.3부터 제공되며, C API는 2.4부터 제공됨)로 구현하거나, mxDateTime 패키지(1.5.2 이후의 모든 파이썬 버전에서 사용 가능)를 사용하여 구현할 수 있습니다. 이 둘은 모두 파이썬과 C 수준에서 필요한 모든 생성자와 메서드를 제공합니다.
  • 다음은 제네릭 생성자에 작업을 위임하는, 유닉스 틱 기반의 날짜/시간 생성자 구현 예시입니다:
    import time
    
    def DateFromTicks(ticks):
        return Date(*time.localtime(ticks)[:3])
    
    def TimeFromTicks(ticks):
        return Time(*time.localtime(ticks)[3:6])
    
    def TimestampFromTicks(ticks):
        return Timestamp(*time.localtime(ticks)[:6])
    
  • Binary 객체에 선호되는 객체 타입은 표준 파이썬 1.5.2부터 제공되는 버퍼 타입입니다. 자세한 내용은 파이썬 문서를 참조하십시오. C 인터페이스에 대한 정보는 파이썬 소스 배포판의 Include/bufferobject.hObjects/bufferobject.c를 참조하십시오.
  • 이 파이썬 클래스는 description의 type code 필드가 하나의 타입 객체에 대해 여러 값을 산출하는 경우에도 위의 타입 객체를 구현할 수 있게 해 줍니다:
    class DBAPITypeObject:
        def __init__(self,*values):
            self.values = values
        def __cmp__(self,other):
            if other in self.values:
                return 0
            if other < self.values:
                return 1
            else:
                return -1
    

    결과로 나온 타입 객체는 생성자에 전달된 모든 값과 비교했을 때 같습니다.

  • 다음은 위에서 정의한 예외 계층 구조를 구현하는 파이썬 코드 조각입니다 [10]:
    class Error(Exception):
        pass
    
    class Warning(Exception):
        pass
    
    class InterfaceError(Error):
        pass
    
    class DatabaseError(Error):
        pass
    
    class InternalError(DatabaseError):
        pass
    
    class OperationalError(DatabaseError):
        pass
    
    class ProgrammingError(DatabaseError):
        pass
    
    class IntegrityError(DatabaseError):
        pass
    
    class DataError(DatabaseError):
        pass
    
    class NotSupportedError(DatabaseError):
        pass
    

    C에서는 PyErr_NewException(fullname, base, NULL) API를 사용하여 예외 객체를 생성할 수 있습니다.

선택적 DB API 확장

DB API 2.0의 수명 동안, 모듈 작성자들은 이 DB API 명세에서 요구하는 것 이상으로 구현을 확장해온 경우가 많았습니다. 호환성을 향상시키고 명세의 향후 버전으로의 깔끔한 업그레이드 경로를 제공하기 위해, 이 절에서는 핵심 DB API 2.0 명세에 대한 일련의 공통 확장을 정의합니다.

모든 DB API 선택적 기능과 마찬가지로, 데이터베이스 모듈 작성자는 이러한 추가 속성과 메서드를 구현하지 않아도 되며(이 경우 사용하려고 하면 AttributeError가 발생합니다), 가용성을 실행 시점에만 확인할 수 있는 경우에는 NotSupportedError를 발생시켜도 됩니다.

이러한 확장의 사용을 Python 경고 프레임워크를 통해 Python 경고를 발생시킴으로써 프로그래머에게 선택적으로 드러나도록 하자는 제안이 있었습니다. 이 기능을 유용하게 만들려면, 경고 메시지를 마스킹할 수 있도록 표준화해야 합니다. 이러한 표준 메시지는 아래에서 경고 메시지로 지칭됩니다.

Cursor.rownumber
이 읽기 전용 속성은 결과 집합에서 커서의 현재 0 기반 인덱스를 제공해야 하며, 인덱스를 확인할 수 없는 경우 None을 제공해야 합니다.

이 인덱스는 시퀀스(결과 집합) 내에서 커서의 인덱스로 볼 수 있습니다. 다음 페치 연산은 그 시퀀스에서 .rownumber로 인덱싱된 행을 페치합니다.

경고 메시지: “DB-API extension cursor.rownumber used”

Connection.Error, Connection.ProgrammingError
DB API 표준에서 정의하는 모든 예외 클래스는 (모듈 스코프에서 사용할 수 있는 것에 더해) Connection 객체에 속성으로 노출되어야 합니다.

이러한 속성은 다중 연결 환경에서 오류 처리를 단순화합니다.

경고 메시지: “DB-API extension connection.<exception> used”

Cursor.connection
이 읽기 전용 속성은 커서가 생성된 Connection을 참조로 반환합니다.

이 속성은 다중 연결 환경에서 다형적 코드를 작성하는 것을 단순화합니다.

경고 메시지: “DB-API extension cursor.connection used”

Cursor.scroll(value [, mode=’relative’ ])
mode에 따라 결과 집합 내에서 커서를 새 위치로 스크롤합니다.

mode가 relative(기본값)이면 value는 결과 집합 내 현재 위치에 대한 오프셋으로 취급되며, absolute로 설정되면 value는 절대 목표 위치를 나타냅니다.

스크롤 작업이 결과 집합을 벗어나게 되는 경우 IndexError가 발생해야 합니다. 이 경우 커서 위치는 정의되지 않은 상태로 남습니다(이상적으로는 커서를 전혀 이동시키지 않는 것입니다).

Note

이 메서드는 가능하다면 네이티브 스크롤 가능 커서를 사용해야 하며, 그렇지 않으면 전방향 전용 스크롤 가능 커서에 대한 에뮬레이션으로 대체해야 합니다. 이 메서드는 특정 작업이 데이터베이스에서 지원되지 않음(예: 후방 스크롤)을 알리기 위해 NotSupportedError를 발생시킬 수 있습니다.

경고 메시지: “DB-API extension cursor.scroll() used”

Cursor.messages
이는 인터페이스가 이 커서에 대해 기저 데이터베이스로부터 수신하는 모든 메시지에 대한 튜플(예외 클래스, 예외 값)을 추가하는 Python 리스트 객체입니다.

이 리스트는 과도한 메모리 사용을 피하기 위해 .fetch*() 호출을 제외한 모든 표준 커서 메서드 호출에 의해(호출을 실행하기 전에) 자동으로 지워지며, del cursor.messages[:]를 실행하여 지울 수도 있습니다.

데이터베이스에서 생성된 모든 오류 및 경고 메시지가 이 리스트에 저장되므로, 이 리스트를 확인하면 사용자가 메서드 호출의 올바른 동작을 검증할 수 있습니다.

이 속성의 목적은 자주 문제를 일으키는 Warning 예외의 필요성을 없애는 것입니다(일부 경고는 실제로 정보 제공 성격만 가집니다).

경고 메시지: “DB-API extension cursor.messages used”

Connection.messages
목록의 메시지가 연결과 관련된다는 점을 제외하면 Cursor.messages_와 동일합니다.

과도한 메모리 사용을 방지하기 위해 모든 표준 연결 메서드 호출이 실행되기 전에 목록이 자동으로 지워지며, del connection.messages[:]을 실행하여 지울 수도 있습니다.

경고 메시지: “DB-API extension connection.messages used”

Cursor.next()
현재 실행 중인 SQL 문에서 다음 행을 .fetchone()와 동일한 의미로 반환합니다. Python 버전 2.2 이상에서는 결과 집합이 소진되면 StopIteration 예외가 발생합니다. 이전 버전에는 StopIteration 예외가 없으므로 대신 이 메서드에서 IndexError를 발생시켜야 합니다.

경고 메시지: “DB-API extension cursor.next() used”

Cursor.__iter__()
커서를 반복 프로토콜 [8]과 호환되도록 자신을 반환합니다.

경고 메시지: “DB-API extension cursor.__iter__() used”

Cursor.lastrowid
이 읽기 전용 속성은 마지막으로 수정된 행의 rowid를 제공합니다(대부분의 데이터베이스는 단일 INSERT 작업이 수행된 경우에만 rowid를 반환합니다). 작업에서 rowid를 설정하지 않거나 데이터베이스가 rowid를 지원하지 않는 경우 이 속성은 None으로 설정되어야 합니다.

마지막으로 실행된 문이 둘 이상의 행을 수정한 경우에는 .lastrowid의 의미가 정의되지 않습니다. 예를 들어 INSERT.executemany()를 사용하는 경우가 이에 해당합니다.

경고 메시지: “DB-API extension cursor.lastrowid used”

Connection.autocommit
연결의 autocommit 모드를 조회하고 설정하는 속성입니다.

연결이 autocommit(비트랜잭션) 모드로 작동 중이면 True를 반환합니다. 연결이 수동 커밋(트랜잭션) 모드로 작동 중이면 False를 반환합니다.

속성을 True 또는 False로 설정하면 그에 따라 연결 모드가 조정됩니다.

설정을 True에서 False로 변경하여 autocommit을 비활성화하면 데이터베이스가 autocommit 모드를 종료하고 새 트랜잭션을 시작합니다. False에서 True로 변경하여 autocommit을 활성화하는 경우 보류 중인 트랜잭션을 처리하는 방식은 데이터베이스에 따라 달라집니다. [12]

지원 중단 알림: 여러 데이터베이스 모듈이 이 속성의 읽기 및 쓰기를 모두 구현하더라도, 속성에 값을 기록하여 autocommit 모드를 설정하는 기능은 지원 중단되었습니다. 이렇게 하면 I/O 및 관련 예외가 발생할 수 있어 비동기 컨텍스트에서 구현하기 어려워지기 때문입니다. [13]

경고 메시지: “DB-API extension connection.autocommit used”

선택적 오류 처리 확장

핵심 DB API 사양은 사용자에게 오류를 보고하기 위해 발생시킬 수 있는 일련의 예외만 도입합니다. 경우에 따라 예외가 프로그램의 흐름을 지나치게 방해하거나 실행 자체를 불가능하게 만들 수도 있습니다.

이러한 경우와 데이터베이스를 다룰 때 오류 처리를 단순화하기 위해, 데이터베이스 모듈 작성자는 사용자 정의 오류 처리기를 구현할 수 있습니다. 이 절에서는 이러한 오류 처리기를 정의하는 표준 방법을 설명합니다.

Connection.errorhandler, Cursor.errorhandler
오류 조건이 충족될 때 호출할 오류 처리기를 참조하는 읽기/쓰기 특성입니다.

처리기는 다음 인자를 받는 Python 호출 가능 객체여야 합니다.

errorhandler(connection, cursor, errorclass, errorvalue)

여기서 connection은 커서가 작동하는 연결에 대한 참조이고, cursor는 커서에 대한 참조이며(오류가 커서에 적용되지 않는 경우에는 None입니다), errorclasserrorvalue를 생성자 인자로 사용하여 인스턴스화할 오류 클래스입니다.

표준 오류 처리기는 적절한 .messages 속성(Connection.messages 또는 Cursor.messages)에 오류 정보를 추가하고, 주어진 errorclasserrorvalue 매개변수로 정의된 예외를 발생시켜야 합니다.

.errorhandler가 설정되지 않은 경우(특성이 None인 경우) 위에서 설명한 표준 오류 처리 방식을 적용해야 합니다.

Warning Message: “DB-API extension .errorhandler used”

커서는 커서 생성 시 연결 객체에서 .errorhandler 설정을 상속해야 합니다.

선택적 2단계 커밋 확장

많은 데이터베이스는 여러 데이터베이스 연결과 기타 리소스에 걸친 트랜잭션을 관리할 수 있도록 하는 2단계 커밋(TPC)을 지원합니다.

데이터베이스 백엔드가 2단계 커밋을 지원하고 데이터베이스 모듈 작성자가 이 지원을 노출하려는 경우 다음 API를 구현해야 합니다. 데이터베이스 백엔드의 2단계 커밋 지원 여부를 런타임에만 확인할 수 있는 경우에는 NotSupportedError를 발생시켜야 합니다.

TPC 트랜잭션 ID

많은 데이터베이스가 XA 사양을 따르므로 트랜잭션 ID는 세 가지 구성 요소로 구성됩니다.

  • 형식 ID
  • 전역 트랜잭션 ID
  • 분기 한정자

특정 전역 트랜잭션에서 처음 두 구성 요소는 모든 리소스에 대해 동일해야 합니다. 전역 트랜잭션의 각 리소스에는 서로 다른 분기 한정자를 할당해야 합니다.

여러 구성 요소는 다음 기준을 충족해야 합니다.

  • 형식 ID: 음이 아닌 32비트 정수입니다.
  • 전역 트랜잭션 ID 및 분기 한정자: 길이가 64자를 넘지 않는 바이트 문자열입니다.

트랜잭션 ID는 .xid() Connection 메서드로 생성합니다.

.xid(format_id, global_transaction_id, branch_qualifier)
이 연결의 .tpc_*() 메서드에 전달하기에 적합한 트랜잭션 ID 객체를 반환합니다.

데이터베이스 연결이 TPC를 지원하지 않으면 NotSupportedError가 발생합니다.

.xid() 가 반환하는 객체의 유형은 정의되지 않지만, 세 구성 요소에 액세스할 수 있도록 시퀀스 동작을 제공해야 합니다. 규격을 준수하는 데이터베이스 모듈은 트랜잭션 ID를 사용자 지정 객체 대신 튜플로 나타낼 수 있습니다.

TPC 연결 메서드

.tpc_begin(xid)
주어진 트랜잭션 ID xid로 TPC 트랜잭션을 시작합니다.

이 메서드는 트랜잭션 외부에서 호출해야 합니다(, 마지막 .commit() 또는 .rollback() 이후 아무것도 실행되지 않아야 합니다).

또한 TPC 트랜잭션 내에서 .commit() 또는 .rollback()을 호출하는 것은 오류입니다. 애플리케이션이 활성 TPC 트랜잭션 중에 .commit() 또는 .rollback()을 호출하면 ProgrammingError가 발생합니다.

데이터베이스 연결이 TPC를 지원하지 않으면 NotSupportedError가 발생합니다.

.tpc_prepare()
.tpc_begin()로 시작된 트랜잭션의 첫 번째 단계를 수행합니다. 이 메서드가 TPC 트랜잭션 외부에서 호출되면 ProgrammingError가 발생해야 합니다.

.tpc_prepare()을 호출한 후에는 .tpc_commit()또는 .tpc_rollback()이 호출될 때까지 어떤 문도 실행할 수 없습니다.

.tpc_commit([ xid ])
인자 없이 호출하면 .tpc_commit().tpc_prepare()로 미리 준비된 TPC 트랜잭션을 커밋합니다.

.tpc_commit().tpc_prepare()보다 먼저 호출하면 단일 단계 커밋이 수행됩니다. 전역 트랜잭션에 단일 리소스만 참여하는 경우 트랜잭션 관리자가 이렇게 처리할 수 있습니다.

트랜잭션 ID xid를 사용해 호출하면 데이터베이스가 해당 트랜잭션을 커밋합니다. 잘못된 트랜잭션 ID가 제공되면 ProgrammingError가 발생합니다. 이 형식은 트랜잭션 외부에서 호출해야 하며, 복구에 사용하도록 고안되었습니다.

반환되면 TPC 트랜잭션이 종료됩니다.

.tpc_rollback([ xid ])
인자 없이 호출하면 .tpc_rollback()은 TPC 트랜잭션을 롤백합니다. .tpc_prepare() 전이나 후에 호출할 수 있습니다.

트랜잭션 ID xid를 사용해 호출하면 해당 트랜잭션을 롤백합니다. 잘못된 트랜잭션 ID가 제공되면 ProgrammingError가 발생합니다. 이 형식은 트랜잭션 외부에서 호출해야 하며, 복구에 사용하도록 고안되었습니다.

반환되면 TPC 트랜잭션이 종료됩니다.

.tpc_recover()
.tpc_commit(xid) 또는 .tpc_rollback(xid)와 함께 사용하기에 적합한 보류 중인 트랜잭션 ID 목록을 반환합니다.

데이터베이스가 트랜잭션 복구를 지원하지 않으면 빈 목록을 반환하거나 NotSupportedError를 발생시킬 수 있습니다.

자주 묻는 질문

데이터베이스 SIG는 DB API 사양에 관한 반복되는 질문을 자주 접합니다. 이 절에서는 사람들이 사양과 관련해 때때로 겪는 몇 가지 문제를 다룹니다.

질문:

.fetch*()로 반환된 튜플로 딕셔너리를 구성하려면 어떻게 해야 합니까?

답변:

이 작업을 위한 여러 기존 도구에서 보조 기능을 제공합니다. 대부분은 커서 속성 .description에 정의된 열 이름을 행 딕셔너리의 키를 위한 기반으로 사용하는 접근 방식을 사용합니다.

이 접근 방식에는 몇 가지 단점이 있으므로 DB API 사양을 확장하여 .fetch*() 메서드에서도 딕셔너리 반환 값을 지원하지 않는다는 점에 유의하십시오.

  • 일부 데이터베이스는 대소문자를 구분하는 열 이름을 지원하지 않거나, 이를 모두 소문자 또는 모두 대문자로 자동 변환합니다.
  • 쿼리에서 생성된 결과 집합의 열(예: SQL 함수를 사용하여 생성된 열)은 테이블 열 이름에 대응하지 않으며, 데이터베이스는 일반적으로 이러한 열에 대해 매우 데이터베이스별적인 방식으로 이름을 생성합니다.

그 결과, 딕셔너리 키를 통한 열 접근 방식이 데이터베이스마다 달라져 이식 가능한 코드를 작성할 수 없습니다.

버전 1.0에서 버전 2.0으로의 주요 변경 사항

Python Database API 2.0에서는 버전 1.0과 비교하여 몇 가지 주요 변경 사항을 도입합니다. 이러한 변경 사항 중 일부로 인해 기존 DB API 1.0 기반 스크립트가 중단되므로, 이를 반영하기 위해 주 버전 번호를 조정했습니다.

1.0에서 2.0으로 변경된 가장 중요한 사항은 다음과 같습니다.

  • 별도의 dbi 모듈이 필요하지 않게 되었으며, 해당 기능이 모듈 인터페이스 자체에 통합되었습니다.
  • 날짜/시간 값을 위한 새로운 생성자와 Type Objects가 추가되었으며, RAW 타입 객체의 이름이 BINARY로 변경되었습니다. 그 결과로 만들어진 집합은 최신 SQL 데이터베이스에서 일반적으로 사용되는 모든 기본 데이터 유형을 포괄해야 합니다.
  • 더 나은 데이터베이스 바인딩을 제공하기 위해 새로운 상수(apilevel, threadsafety, paramstyle)와 메서드(.executemany(), .nextset())가 추가되었습니다.
  • 저장 프로시저를 호출하는 데 필요한 .callproc() 의 의미가 이제 명확하게 정의되었습니다.
  • .execute() 의 반환 값 정의가 변경되었습니다. 이전에는 반환 값이 SQL 문 유형에 기반했지만(올바르게 구현하기 어려웠습니다) 이제는 정의되지 않습니다. 대신 더 유연한 .rowcount 속성을 사용하십시오. 모듈은 이전 방식의 반환 값을 자유롭게 반환할 수 있지만, 이제 사양에서 이를 요구하지 않으므로 데이터베이스 인터페이스에 따라 달라지는 것으로 간주해야 합니다.
  • 클래스 기반 Exceptions가 명세에 포함되었습니다. 모듈 구현자는 정의된 예외 클래스를 서브클래싱하여 이 사양에 정의된 예외 구조를 자유롭게 확장할 수 있습니다.

DB API 2.0 사양에 게시 후 추가된 사항:

  • 핵심 기능 집합에 대한 추가적인 선택적 DB API 확장이 정의되었습니다.

미해결 문제

버전 2.0 사양은 버전 1.0에서 미해결 상태로 남아 있던 많은 질문을 명확히 설명하지만, 향후 버전에서 해결해야 할 문제가 여전히 남아 있습니다.

  • 새로운 결과 집합을 사용할 수 있는 경우 .nextset() 에 대한 유용한 반환 값을 정의하십시오.
  • 손실 없는 화폐 및 소수 교환 형식으로 사용할 수 있도록 decimal moduleDecimal 객체를 통합하십시오.

각주

감사의 말

2001년에 Python Database API Specification 2.0을 원래 HTML 형식에서 PEP 형식으로 변환해준 Andrew Kuchling에게 깊이 감사드립니다.

2008년에 2단계 커밋 API 확장의 표준화로 이어진 논의를 이끌어준 James Henstridge에게 깊이 감사드립니다.

2012년에 명세를 텍스트 PEP 형식에서 다양한 부분으로의 링크를 가능하게 하는 ReST PEP 형식으로 변환해준 Daniele Varrazzo에게 깊이 감사드립니다.