즐겁게!! 자신있게!! 살아보세!!

재밌는 인생을 위하여! 영촤!

Dev Log/Python

[Dev log] python pymysql.err.InterfaceError: (0, '')

Godwony 2021. 3. 4. 13:50
728x90
반응형

python 커뮤니티에서 도움 요청이 왔었습니다.

 

저도 사실 많이 알고 있는건 아니지만 아는 한도 내에서 말씀드렸습니다. 

 

API 에서 받은 데이터를 DB로 보내주는 코드였는데

pymysql.err.InterfaceError: (0, '') 

 

이런 문제가 발생 했죠..

 

 

도움을 요청하신분이 MySQL을 사용하시는데 Python과 DB 연결 원리가 잘 이해가 안 되신다고 하더라고요

 

아래의 내용은 교과서 적인 내용인데 참고하시구요

 

  1. PyMySql 모듈을 import 한다
  2. pymysql.connect() 메서드를 사용하여 MySQL에 Connect 한다. 호스트명, 로그인, 암호, 접속할 DB 등을 파라미터로 지정한다.
  3. DB 접속이 성공하면, Connection 객체로부터 cursor() 메서드를 호출하여 Cursor 객체를 가져온다. DB 커서는 Fetch 동작을 관리하는 데 사용되는데, 만약 DB 자체가 커서를 지원하지 않으면, Python DB API에서 이 커서 동작을 Emulation 하게 된다.
  4. Cursor 객체의 execute() 메서드를 사용하여 SQL 문장을 DB 서버에 보낸다.
  5. SQL 쿼리의 경우 Cursor 객체의 fetchall(), fetchone(), fetchmany() 등의 메서드를 사용하여 데이터를 서버로부터 가져온 후, Fetch 된 데이타를 사용한다.
  6. 삽입, 갱신, 삭제 등의 DML(Data Manipulation Language) 문장을 실행하는 경우, INSERT/UPDATE/DELETE 후 Connection 객체의 commit() 메서드를 사용하여 데이타를 확정 갱신한다.
  7. 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의 문을 열고 작업 후에 저장하고 닫으세요

 

728x90
반응형