본문 바로가기
Python/Study

[Python] asyncpg ─ PostgreSQL 비동기 연결

by VANCODER 2024. 11. 21.

asyncpg 

: PostgreSQLPython/asyncio를 위해 특별히 설계된 데이터베이스 인터페이스 라이브러리

  • Python 3.8 이상 필요, PostgreSQL 버전 9.5부터 17까지 지원
  • 다른 PostgreSQL 버전이나 PostgreSQL 프로토콜을 구현하는 다른 데이터베이스도 작동할 수 있지만, 현재는 적극적으로 테스트되지 않음

1. PostgreSQL 연결

1-1. asyncpg 설치

pip install asyncpg

 

1-2. asyncpg 연결

`asyncpg.connect()` : PostgreSQL 서버에 연결을 설정하는 코루틴
  • 연결 매개변수는 연결 URI(dsn) 형식으로 지정하거나, 구체적인 키워드 인수로 지정
async connect(dsn=None, *, host=None, port=None, 
user=None, password=None, passfile=None, database=None, 
loop=None, timeout=60, statement_cache_size=100, 
max_cached_statement_lifetime=300, max_cacheable_statement_size=15360, 
command_timeout=None, ssl=None, direct_tls=None, 
connection_class=<class 'asyncpg.connection.Connection'>, 
record_class=<class 'asyncpg.Record'>, server_settings=None, 
target_session_attrs=None, krbsrvname=None, gsslib=None)

 

매개변수

1. dsn

: 연결 인수를 단일 문자열로 지정한 libpq 연결 URI 형식

postgres://user:password@host:port/database?option=value
<주의>
- URI는 유효해야 함
- 모든 구성 요소는 `urllib.parse.quote_plus()`로 올바르게 인코딩되어야 함
- 리터럴 IPv6 주소는 [대괄호]로 묶어야 함
- e.g. `postgres://dbuser@[fe80::1ff:fe23:4567:890a%25eth0]/dbname`

 

2. host
: 데이터베이스 서버에 연결할 호스트 주소

  • IP 주소, 도메인 이름, Unix 도메인 소켓 디렉토리 경로 지정
  • 지정하지 않으면,
    1. dsn에서 파싱된 값
    2. PGHOST 환경 변수 값
    3. Unix의 경우 일반적으로 사용하는 PostgreSQL Unix 도메인 소켓 디렉토리들이 순차적으로 시도
    4. 마지막으로 "localhost" 시도

3. port
: 서버 호스트에 연결할 포트 번호

  • Unix 도메인 소켓 파일 확장자도 포트로 사용할 수 있음
  • 지정하지 않으면,
    1. dsn에서 파싱된 값
    2. PGPORT 환경 변수 값
    3. 기본값인 5432 사용

4. user
: 인증에 사용되는 데이터베이스 역할의 이름

  • 지정하지 않으면,
    1. dsn에서 파싱된 값
    2. PGUSER 환경 변수 값
    3. 운영 체제에서 실행 중인 애플리케이션의 사용자 이름 사용

 

5. database
: 연결할 데이터베이스의 이름

  • 지정하지 않으면,
    1. dsn에서 파싱된 값
    2. PGDATABASE 환경 변수 값
    3. user 인수에서 계산된 값 사용

6. password

: 서버가 인증을 요구하는 경우 사용할 비밀번호

  • 지정하지 않으면,
    1. dsn에서 파싱된 값
    2. PGPASSWORD 환경 변수 값 사용
      • 환경 변수 사용은 권장 X, 대신 passfile 사용

 

반환 값

  • 새로운 Connection 객체

 

e.g. PostgreSQL 서버에 연결하여 pg_type 테이블에서 모든 레코드 조회

import asyncpg
import asyncio
async def run():
    con = await asyncpg.connect(user='postgres')
    types = await con.fetch('SELECT * FROM pg_type')
    print(types)

asyncio.run(run())

 

1-3. asyncpg 연결 해제

`async close(*, timeout=None)` : 연결을 정상적으로 종료

 

매개변수

  • timeout (float): (선택사항) 연결 종료를 위한 제한 시간(초 단위)

2. 예제

import asyncio
import asyncpg
import datetime

async def main():
    # Establish a connection to an existing database named "test"
    # as a "postgres" user.
    conn = await asyncpg.connect('postgresql://postgres@localhost/test')
    # Execute a statement to create a new table.
    await conn.execute('''
        CREATE TABLE users(
            id serial PRIMARY KEY,
            name text,
            dob date
        )
    ''')

    # Insert a record into the created table.
    await conn.execute('''
        INSERT INTO users(name, dob) VALUES($1, $2)
    ''', 'Bob', datetime.date(1984, 3, 1))

    # Select a row from the table.
    row = await conn.fetchrow(
        'SELECT * FROM users WHERE name = $1', 'Bob')
    # *row* now contains
    # asyncpg.Record(id=1, name='Bob', dob=datetime.date(1984, 3, 1))

    # Close the connection.
    await conn.close()

asyncio.run(main())
  • 데이터베이스와의 상호작용은 일반적으로 `connect()` 호출로 시작
    • 새로운 데이터베이스 세션 설정
    • 쿼리를 실행하고 트랜잭션을 관리하는 메서드를 제공하는 새로운 Connection 인스턴스를 반환
asyncpg는 쿼리 인수에 대해 PostgreSQL의 기본 문법인 `$n`을 사용

 

타입 변환

asyncpg는 PostgreSQL의 데이터 타입을 자동으로 대응되는 Python 타입으로 변환

PostgreSQL Type Python Type
anyarray list
anyenum str
anyrange asyncpg.Range, tuple
anymultirange list[asyncpg.Range ], list[tuple ] 1
record asyncpg.Record, tuple, Mapping
bit, varbit asyncpg.BitString
bool bool
box asyncpg.Box
bytea bytes
char, name, varchar, text, xml str
cidr ipaddress.IPv4Network, ipaddress.IPv6Network
inet ipaddress.IPv4Interface, ipaddress.IPv6Interface, ipaddress.IPv4Address, ipaddress.IPv6Address 2
macaddr str
circle asyncpg.Circle
date datetime.date
time offset-naïve datetime.time
time with time zone offset-aware datetime.time
timestamp offset-naïve datetime.datetime
timestamp with time zone offset-aware datetime.datetime
interval datetime.timedelta
float, double precision float 3
smallint, integer, bigint int
numeric Decimal
json, jsonb str
line asyncpg.Line
lseg asyncpg.LineSegment
money str
path asyncpg.Path
point asyncpg.Point
polygon asyncpg.Polygon
uuid uuid.UUID
tid tuple
<참고> 부동소수점 타입은 파이썬의 부동소수점 값으로 디코딩될 때 정확히 일치하지 않을 수 있음
- 이는 제한된 정밀도의 부동소수점 타입의 구현에 기인한 것
- 진수 표현이 일치해야 할 경우, 쿼리에서 double 또는 numeric으로 형변환을 수행

참고 문서

https://magicstack.github.io/asyncpg/current/index.html