python 커뮤니티에서 도움 요청이 왔었습니다.
저도 사실 많이 알고 있는건 아니지만 아는 한도 내에서 말씀드렸습니다.
API 에서 받은 데이터를 DB로 보내주는 코드였는데
pymysql.err.InterfaceError: (0, '')
이런 문제가 발생 했죠..
도움을 요청하신분이 MySQL을 사용하시는데 Python과 DB 연결 원리가 잘 이해가 안 되신다고 하더라고요
아래의 내용은 교과서 적인 내용인데 참고하시구요
- PyMySql 모듈을 import 한다
- pymysql.connect() 메서드를 사용하여 MySQL에 Connect 한다. 호스트명, 로그인, 암호, 접속할 DB 등을 파라미터로 지정한다.
- DB 접속이 성공하면, Connection 객체로부터 cursor() 메서드를 호출하여 Cursor 객체를 가져온다. DB 커서는 Fetch 동작을 관리하는 데 사용되는데, 만약 DB 자체가 커서를 지원하지 않으면, Python DB API에서 이 커서 동작을 Emulation 하게 된다.
- Cursor 객체의 execute() 메서드를 사용하여 SQL 문장을 DB 서버에 보낸다.
- SQL 쿼리의 경우 Cursor 객체의 fetchall(), fetchone(), fetchmany() 등의 메서드를 사용하여 데이터를 서버로부터 가져온 후, Fetch 된 데이타를 사용한다.
- 삽입, 갱신, 삭제 등의 DML(Data Manipulation Language) 문장을 실행하는 경우, INSERT/UPDATE/DELETE 후 Connection 객체의 commit() 메서드를 사용하여 데이타를 확정 갱신한다.
- Connection 객체의 close() 메서드를 사용하여 DB 연결을 닫는다.
좀 더 풀어서 설명하자면 아래와 같은 코드로 크게 4가지 동작이 있다고 보시면 됩니다.
import pymysql
conn = pymysql.connect(host='localhost', user='tester', password='7890',
db='testdb', charset='utf8')
curs = conn.cursor() # 1. DB의 문을 열다
sql = """insert into customer(name,category,region)
values (%s, %s, %s)"""
curs.execute(sql, ('홍길동', 1, '서울')) # 2. 작업을 한다.
curs.execute(sql, ('이연수', 2, '서울')) # 2. 작업을 한다.
conn.commit() # 3. 저장한다.
conn.close() # 4. DB의 문을 닫는다.
이런 동작을 앞 서 작성 한 이유는 conn.close()에 있습니다.
그리고 제일 중요한 interfacerror의 원인은 문을 닫지 않아서 발생한 에러 이기도 합니다.
pymysql.err.InterfaceError: (0, '')
Connection leak라고 부르기도 해요
Connection leak의 대응 방안으로는 에러가 발생하면 예외처리에서 강제로 닫게 (conn.close()) 를 해주는 것이 되겠습니다.
자세한 내용은
SQL Connection을 열고 프로그램 중간에서 에러가 발생하면,
Connection은 그대로 열려 있는 상태로 있을 수 있다.
이렇게 오픈되어 있는 Connection이 증가하면,
나중에 새로운 Connection을 오픈할 수 없게 되는데,
이를 Connection Leak이라 부른다.
이러한 Connection Leak을 막기 위하여
아래 예제와 같이 try... finally 블력을 사용하여 finally에서 항상 Conneciton을 Close 해야한다.
import pymysql
conn = pymysql.connect(host='localhost', user='tester', password='7890',
db='testdb', charset='utf8')
try:
# INSERT
with conn.cursor() as curs:
sql = "insert into customer(name,category,region) values (%s, %s, %s)"
curs.execute(sql, ('이광수', 1, '서울'))
conn.commit()
# SELECT
with conn.cursor() as curs:
sql = "select * FROM customer"
curs.execute(sql)
rs = curs.fetchall()
for row in rs:
print(row)
finally:
conn.close()
위 예제의 try 블록을 보면, INSERT와 SELECT 문을 각기 다른 커서에서 사용하고 있다. 첫 번째 INSERT 실행 시 with 문으로 커서를 만들어 자동으로 커서 리소스가 해제되도록 하였고, 두 번째 SELECT 시에도 with 문으로 해당 커서가 자동 해제되도록 하였다. 이러한 예제에서 보듯이, SQL 객체들을 다룰 때 try... finally 나 with 문을 적절히 사용하여 리소스를 해제해 주는 것이 좋다.
인용 출처 : pythonstudy.xyz/python/article/202-MySQL-%EC%BF%BC%EB%A6%AC
마무리하겠습니다.
DB의 문을 열고 작업 후에 저장하고 닫으세요
'Dev Log > Python' 카테고리의 다른 글
[Dev log] 파일형식의 log를 DB log 로 튜닝하자 (0) | 2021.01.20 |
---|---|
[Dev log] selenium page down, scroll down, 스크롤 내리기 (1) | 2021.01.14 |
[Dev log] Python Web crawling selenium for Naver Login (0) | 2021.01.12 |
[Dev log] Python 개행 문자(\n) 삭제 - map, lambda, strip (0) | 2021.01.11 |
[Dev log] Python jupyter notebook에서 kenerl이 안보일때 (0) | 2020.06.05 |