Python 28

SQLAlchemy에서 session.commit()과 session.flush()의 차이

SQLAlchemy를 사용해서 어떤 데이터를 추가/변경 또는 삭제를 할 때 session.commit() 메소드와 session.flush() 메소드가 자주 사용되어지곤 한다. 기본적으로 둘 다 모든 적용되지 않은 변경 사항들을 저장하는 역할을 하나, session.commit()의 경우에는 한가지 추가적인 작업을 진행하게 되는데, 바로 연결된 모든 객체들을 expire 처리하고 다시 로딩을 한다는 점이다. 이 기능을 하는 여러가지 이유가 있겠지만, 대표적인 이유 중 하나로는 INSERT 후에 autoincrement id 값을 가져오기 위해서가 있다. 복잡한 비즈니스 로직을 구현하다보면 M:N의 문제들이 많이 발생하게 되는데, 이러한 경우 primary key들을 저장하는 매핑 테이블이 존재하기 마련이..

Python/sqlalchemy 2024.02.23

SQLAlchemy Session과 AsyncSession은 synchronizable한 객체일까?

SQLAlchemy에서 세션은 단일 데이터베이스 트랜잭션을 나타내는 변경 가능한 상태 저장 객체이다. 따라서 세션 객체는 신중한 동기화 없이는 동시 스레드 또는 비동기 작업 간에 공유할 수 없다. 세션은 non-concurrent 방식으로 (즉 특정 Session 객체는 한 번에 하나의 스레드 또는 작업에서만) 사용되어야 한다. SQLAlchemy의 asyncio 확장 기능에서 AsyncSession 객체를 사용하는 경우, 이 객체는 Session 객체를 기반으로 만들어지는 단순한 프록시일 뿐이며 동일한 규칙이 적용된다. AsyncSession은 동기화되지 않고 mutable(변경 가능)한 stateful한 특성을 가지는 객체이므로 여러 asyncio 작업에서 단일 인스턴스의 AsyncSession을 ..

Python/sqlalchemy 2024.02.23

Ray 개요 :: 파이썬 기반 분산 컴퓨팅

Ray는 파이썬 데이터 과학 커뮤니티를 위해서 만든 유연한 분산 컴퓨팅 프레임워크이다. Ray는 간결한 구조를 바탕으로 분산 프로그램을 효율적으로 작성 가능하다. 노트북에서 Ray를 사용하면 파이썬 프로그램을 효율적으로 병렬화하고, 로컬에서 테스트한 코드를 변경 없이도 클러스터에서 실행한다. Ray Core(Ray의 기본 API)는 C++로 개발되었으나, 애초에 파이썬을 위한 프레임워크이며 자바를 비롯한 여러 언어를 바인딩하도록 설계되었다. Ray가 데이터 과학 생태계에 여러 중요한 언어를 지원하기 때문에 데이터 과학자들 및 엔지니어들이 더 쉽게 효율적인 분산 데이터 처리 파이프라인 및 엔진을 구축할 수 있도록 큰 기여를 했다는 점은 부정할 수 없는 사실이다. 알다시피, 분산 컴퓨팅은 매우 어렵다는 인식..

Python/ray 2024.02.11

파이썬에서 더 빠른 JSON serialization 사용하기

보통 파이썬에서 JSON을 string으로 직렬화(serialization)하거나 직렬화된 데이터로부터 JSON 객체(dict 타입)를 로딩하는 방법은 아래와 같이 json 표준 모듈을 사용하는 것이다. import json data = {'a': 'a', 'b': 'b'} data_str = json.dumps(data) new_data = json.load(data_str) 그러나, 이 표준 라이브러리는 파이썬으로 구현되어 있기 때문에 C/C++이나 Rust로 구현된 구현체들보다 더 느리다. 보통 빠른 JSON 직렬화 및 역직렬화를 위해서는 ujson과 orjson이 사용된다. ujson은 C로 작성된 JSON 모듈의 파이썬 바인딩이다. 해당 라이브러리는 파이썬 3.7부터 지원되고 있다. orjson..

Python 2024.01.22

python psutil을 사용해서 간단한 모니터링 스크립트 구축하기

Bash 스크립트에서 ps를 사용하면 프로세스 정보를 알 수 있듯이, 파이썬에서는 psutil 라이브러리를 사용하면 프로세스 상태를 가져올 수 있는 API를 사용할 수가 있게 된다. https://pypi.org/project/psutil/ 아래는 psutil을 사용해서 작성한 간단한 프로세스 상태 모니터링 스크립트이다. import psutil from datetime import datetime import pandas as pd import time import os def get_size(bytes): """ Returns size of bytes in a nice format """ for unit in ['', 'K', 'M', 'G', 'T', 'P']: if bytes < 1024: ret..

Python 2024.01.02

sqlalchemy로 MySQL 연결 시 필요한 라이브러리

알다시피, sqlalchemy의 기본 데이터베이스는 PostgreSQL이다. 따라서, psycopg나 asyncpg와 같은 PostgreSQL용 드라이버 및 라이브러리는 자동으로 함께 설치가 되나, MySQL을 사용하는 사람들은 필요한 라이브러리를 일일히 추가해주어야 한다. pip install mysqlclient pip install mysql-connector pip install mysql-connector-python 위와 같이 "mysqlclient"와 "mysql-connector", 그리고 "mysql-connector-python"까지 설치를 해주어야 한다. 처음 시도할 때에는 "mysqlclient"와 "mysql-connector"만 설치하고 에러 메시지를 정독하면서 왜 안되는지 열심..

Python/sqlalchemy 2024.01.02

sqlalchemy logging 옵션 끄기

sqlalchemy를 처음 사용할 때에는 계속 나오는 로그들을 어떻게 없앨 수 있을지에 대해서 이리저리 구글링을 많이 해보게 된다. 스택오버플로우를 봐도 잘못된 답변들도 보이고, 결국 30분간 이리저리 삽질을 하다가 나름의 답을 찾아냈다. 아래 코드와 같이 4개의 토픽에 대해서 로그레벨을 ERROR로 설정해놓으면 데이터베이스 에러로 인한 상황을 제외하고는 모든 디버깅 로그나 info 로그가 다 필터링되게 된다. import logging from typing import Any, Generator # from sqlalchemy.sql import text from sqlalchemy import Column, Integer, MetaData, Table, Text, select from sqlmodel..

Python/sqlalchemy 2024.01.02

sqlalchemy에서 joinedload와 Query.join()의 차이점

tl;dr joinedload를 사용하면 JOIN된 전체 attribute들을 select하나, Query.join()은 query의 대상이 되는 table의 항목들만 select의 대상이 된다. 이 글은 SQLAlchemy의 공식 문서를 번역한 것입니다. 원문: https://docs.sqlalchemy.org/en/14/orm/loading_relationships.html#sqlalchemy.orm.joinedload Joinedload는 Query.join()의 사용과 많은 유사점이 있기 때문에, 언제 어떻게 사용해야 하는지에 대해 혼동을 일으키는 경우가 많습니다. Query.join()은 쿼리 결과를 변경하는 데 사용되는 반면, joinedload()는 쿼리 결과를 변경하지 않고 렌더링된 조인의..

Python/sqlalchemy 2023.10.22

Python gc 튜닝을 통한 성능 개선 (Flask 기반 예시 코드)

일반적으로 파이썬 환경은 CPython을 의미하기 때문에, 이 문서에서 다루는 내용 역시 CPython 인터프리터에 대한 실험을 포함하고 있습니다. PyPy나 RustPython과 같은 환경에서는 또 다른 상황이 발생할 수 있다는 점을 미리 고지드립니다. CPython에서 gc의 동작 원리 기본적으로 파이썬의 gc는 reference count를 기반으로 작동을 하게 된다. CPython에서 class 등을 통해 만들어진 인스턴스나 기본형 데이터 등이 생성되게 되면 내부적으로 PyObject 타입의 struct에 대해 memory allocation이 발생하게 된다. 그리고 CPython은 할당된 메모리의 관리를 위해 reference list에 생성된 PyObject에 대한 reference를 추가함으..

Python 2023.10.14

Dropzone.js를 사용해 대용량 파일 업로드 API 성능 개선

파일 업로드 일반적으로 파일 업로드를 할 때에는 multipart/form-data 형식으로 업로드를 진행하도록 API를 디자인하게 된다. 이때, 일반적인 파일들은 파일 크기가 그렇게 크지 않겠지만, 영상 파일과 같이 용량이 GB 단위가 되는 경우에는 단순히 한번의 요청으로 전체 파일을 올리는 것이 매우 어려워지게 된다. 다음 코드는 multipart/form-data 형식으로 데이터를 업로드하기 위한 API를 Flask와 flask-restx로 구현한 간단한 예제이다: import uuid from flask import request, make_response from flask_restx import Resource, Namespace from werkzeug.utils import secure_f..

Python/Flask 2023.10.09