[Python] sqlite3 same thread 문제와 QTablewidget

2023. 9. 19. 07:19IT

데이터베이스의 테이블 두 개를 join해서 QTablewidget을 이용해서 화면에 정보를 뿌리는 프로그램을 만들고 있었다. 항상 그렇지만 데이터베이스에는 사용자에게 보여줄 필요가 없지만 프로그램에 필요한 정보가 있다. 또한 간단한 인덱스로 들어 있어 상태를 표시하는 경우도 있다.이 경우에는 인덱스를 상태에 해당하는 아이콘이나 문자열로 바꾸서 보여줘야 한다. 

그러니까 내가 만든 프로그램은 테이블에 표시를 하는데 엑셀에서 데이터를 보여주듯이 그냥 뿌리기만 하는 것이 아니라 데이터를 변경해서 사용자에게 보여줘야 한다. 

 

그런데 데이터 변경을 하는 작업이 꽤나 시간이 걸리는 작업들이라 테이블에는 간단하게 텍스트로 1차로 보여주고 변경된 데이터를 보여주고자 쓰레드를 이용하려고 했다. 쓰레드를 이용해서 데이터를 처리하기 위해서 테이터베이스에 접근하려고 했는데 다음과 같은 에러메시지를 마주쳤다. 

 

sqlite3.ProgrammingError: SQLite objects created in a thread can only be used in that same thread. The object was created in thread id 7804 and this is thread id 2132.

 

같은 쓰레드에서만 sqlite3 데이터베이스를 접근할 수 있다는 것이다.  간단하게 쓰레드 부터 에러가 나는 부분에 대한 코드는 아래와 같다. 쓰레드를 시작하고 테이블의 내용을 분석하는 그런거다. 

        # 파일분석 Threading
        pesThread = threading.Thread(target=self.PESFileAnalysing, daemon=True)
        pesThread.start()

    def PESFileAnalysing(self):
        while True:
            self.mainListTable.MainTableAnalsys()
            time.sleep(5)
            
##################################################################################            

 	def getNsetAnalysis(self, id):
        sql = "SELECT status cnt FROM PESs where id = ?"
        self._conn.execute(sql, (id, ))
        row = self._conn.fetchall()

        # 0 : 처음 --> 1로 변경
        if int(row[0][0] == 0):
            print(f"분석 필요 {row[0][0]} return True {id}")
            return True
        else:
            print(f"분석 불필요 {row[0][0]} return False {id}")
            return False

    def MainTableAnalsys(self):
        rc = self.mainDataTable.rowCount()
        for i in range(rc):
            data = self.mainDataTable.item(i, 1)
            id = int(data.text())
            print(id)
            self.mainDataTable.setColumnWidth(14, 0)
            # self.mainDataTable.hideColumn(2)
            # if self.getNsetAnalysis(id):
            #     ...
            #     break

 

어떻게 해결을 하면 될까?

사실 해결 방법은 어렵지 않다. 별도로 리스트를 만들어 데이터베이스의 내용을 읽어 온다. 다음에 리스트에서 필요한 정보를 처리하면 된다. 리스트가 아니면 딕셔너리, 자료가 많다면 pandas도 나쁜 선택은 아니라고 생각이 되었다. 먼저 서로 다른 쓰레드에서 리스트를 접근해도 문제가 되지 않을까? 필요하면 테스트를 해 보면 될 것이다. 그런데 난 이 방법을 사용하지 않으려고 한다. 이미 코드를 본 사람은 눈치를 채지 않았을까 싶다. 표를 어차피 사용할 것이기 때문에 자료가 여기저기 흩어져서 발생하는 문제를 일으키고 싶지 않았다. 

 

그냥 표에 불필요한 정보를 출력하고 숨겨 놓고 사용하면 어떨까?

안타깝게도 hideColumn() 메서드를 써서 숨기니 그 너비가 그대로 남아있어 보기가 싫다. 그래서 찾은 방법은 컬럼의 너비를 0으로 만들어 보이지 않게 하는 방법이다. 테이블 맨 뒤에 넣고 테스트를 해 보니 깜쪽같다. 개발 중에는 너비를 그대로 사용하고 나중에는 숨기면 될꺼다. 

 

반응형