윈도우에서 csv 파싱하는 프로그램이 필요해서
python tkinter로 treeview를 이용해 구현해 봤습니다.
일단 기본 기능은 구현해서 log가 몇백줄일때는 그냥 저냥 좀 기다리면 되었는데....
문제는 몇 천, 몇 만 라인 이상되는 csv를 treeview로 insert 하려니 속도가 너무 느립니다. ;;;
그냥 text 로된 csv 파일 한줄씩 읽어서, treeview에 넣어주는 단순한 동작이라 생각했는데
treeview에 한줄씩 insert 하니까 1000라인에 1분씩 걸리네요.
소스로 사용한 csv 파일 약 7천라인을 treeview에 전부 insert 하는데 387초 소요 = 6분 27초
속도가 느린게 컴퓨터가 사양이 딸린것도 아니고... i9 10850K 인데
Python tkiner 라이브러리의 한계인걸까요. ;;;
아님 제가 예제를 발로 짜서 성능이 이모냥인걸까요? ㅠ.ㅠ
도통 혼자서는 속도 개선이 안되서...
캡쳐 화면의 treeview에 insert 반복 수행하는 예제 소스는 아래 링크로 공유 드립니다.
https://github.com/bbyongi/python_treeview
python tkinter에서 treeview 속도는 원래 느린게 맞는 포기해야할 부분인지...
혹시 treeview insert 속도 더 빠르게 할 수 있는 방법 아시면...
파이썬 고수님의 조언 부탁 드립니다.
----------------------------
원하던 바를 해결하여 후기 업데이트 합니다.
1. treeview에서 insert 시 속도가 느린건 스레드 처리 때문이었습니다. ;;
쓰레드로 하지 않고 그냥 treeview로 insert 해보면 1초 이하로 6000천개이상 표시 가능하네요.
2. tksheet라는 훌륭한 라이브러리를 알게 되었습니다.
treeview가 표로 보여주지만 마우스 클릭등으로 실시간 편집은 불가능한데 (코드로 수정하지 않는한)
tksheet는 엑셀이 그대로 GUI로 표현된 느낌으로, 테이블 내 값들을 실시간으로 수정/편집 등이 가능해셔
제가 필요한 상황에서는 treeview 보다 tksheet가 더 좋은 솔루션인것 같습니다.
배경색도 원하는대로 변경할 수 있더라구요.
3. 마지막으로 해결하지 못한 문제는 GUI 프로그래밍이라 UI 업데이트를 위해서 쓰레드로 처리할때
쓰레드에서 GUI 업데이트 하느라 속도가 느린건지 모르겠는데....
쓰레드 처리하면 UI 변경은 먹통되지 않는데, 속도가 느린걸 해결할순 없을지가 숙제인듯 합니다.
일단 제가 구상한 툴 기능에서는 1초내에 결과를 tksheet로 다 표시할 수 있다면
굳이 쓰레드 처리할 필요는 없을것 같아서 쓰레드처리만 삭제하면 해결되는 상황으로 보여집니다.
여러가지로 조언 주셔서 개발한당에서 많이 배워갑니다.
조언 주신 분들께 다시 한번 감사 드립니다.
엇 그게 가능한가요? 한번에 6000라인 결과가 바로 표시되도 상관없는데...
구글링으로 treeview 사용법 배울때 insert 할때 index 인자가 필요해서
예제 따라서 한줄씩 insert 하도록 구현한 상태입니다.
구글링으로 treeview 여러줄 한번에 insert 가능한 예제가 있는지 찾아보고
csv에서 읽은 6천라인 리스트에 담아서 한방에 가능한지 연구좀 해보겠습니다.
조언 감사합니다.
조언 감사합니다.
https://docs.python.org/3/library/tkinter.ttk.html#tkinter.ttk.Treeview.insert
treeview 옵션을 좀 찾아봤는데, treeview에 추가할 가로줄 1개 라인값들을 list로 받는 api 라서 그런지
가로줄 1개 list를 list로 보관한 2차원 list 6000개를 treeview에 insert 해봤자
treeview의 1개 라인에 정보가 낑겨져 버리네요.
구글링 해봐도 treeview에 item을 한방에 insert 하는건 안보이는데 treeview의 한계가 맞는지도 모르겠네요.
혹시, 이글 보시는 다른 고수님 계시면 treeview에 2차원 list로 한방에 insert 가능한 방법 아시면
추가 조언 부탁 드립니다.
이 글이 답일 것 같네요.
링크 감사합니다.
저녁에 정독해보고 개선될지 확인 해보겠습니다.
코드 슥 봤는데 클래스랑 쓰레드 처리는 잘 모르는 초보라서
제가 짠 예제를 뜯어고치는게 가능할지 공부 삽질에 시간이 더 걸릴지
링크의 예제 확인하고 거기에 낑겨 넣는게 빠를지
공부 좀 해보겠습니다.
Win32 에서는 보통
아이템 추가전 WM_SETREDRAW 를 FALSE 로 보내고
아이템 추가하고,
끝나면 WM_SETREDRAW 를 TRUE 로 처리합니다.
https://learn.microsoft.com/ko-kr/windows/win32/gdi/wm-setredraw
해당 컨트롤이 커먼 컨트롤이 아니라 먹힐지 모르겠지만, 윈도우 핸들 구해서 Win32 API 로 해당 메시지 보내보세요.
제가 C만 사용하는 embedded 개발자인데...
취미로 python GUI 프로글매으로 tkinter만 독학한거라서...
필요한 툴들 직접 만들면서 공부하는 수준이라 win32 프로그래밍은 못해서 아쉽습니다.
노하우 공유 삼사합니다.
tksheet 추천 감사합니다.
treeview 랑 비교해서 얼마나 속도차이 나는지 예제 찾아 보겠습니다.
import os
import sys
import time
from datetime import datetime
from tksheet import Sheet
import tkinter as tk
import pandas as pd
def get_line(path):
f_path = open(path, 'r')
line = len(f_path.readlines())
return line
def get_treedata():
total_line = get_line("log.csv")
time_start = datetime.now()
index_num = 0
count_total = 0
with open("log.csv", "r") as f:
treedata = []
for line in f:
count_total += 1
index_num += 1
index_str = str(index_num)
time_diff = ((datetime.now() - time_start).total_seconds())
treeitem = [ f"{count_total}/{total_line}",
'%.3f'%time_diff,
f"{line}",
f"{count_total}",
f"{count_total+10}",
f"{count_total+100}",
f"{count_total+1000}",
f"{count_total+10000}",
f"{count_total+100000}",
]
treedata.append(treeitem)
#if count_total % 100 == 0:
# print(f"count_total = {count_total}, {int(time_diff)} sec")
return treedata
class demo(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.grid_columnconfigure(0, weight=1)
self.grid_rowconfigure(0, weight=1)
self.frame = tk.Frame(self)
self.frame.grid_columnconfigure(0, weight=1)
self.frame.grid_rowconfigure(0, weight=1)
self.sheet = Sheet(
self.frame,
data=get_treedata(),
)
self.sheet.enable_bindings()
self.frame.grid(row=0, column=0, sticky="nswe")
self.sheet.grid(row=0, column=0, sticky="nswe")
app = demo()
app.mainloop()
와 예제 감사합니다.
tksheet 사용해서 csv 읽어온거 그대로 통으로 넣는건 확인하고
csv 읽어온걸 필드별로 modify 해서 넣는 방법에서 막혀 있었는데
data=get_treedata()에서 리스트로 저장해 넣는 예제 참고하여 확인해 보겠습니다.
특정 셀값에 따라, 해당 라인 배경색을 바꿔서 필터링 효과를 줘보고 싶은데 (treeview에서는 tag 기능으로 색상 적용 가능)
이제 tksheet에서 각 셀별로 특정값 비교해 배경색 바꾸는게 가능한지만 더 찾아보면 될것 같습니다.
tksheet 좋은거 배워갑니다.
https://github.com/ragardner/tksheet/wiki/Version-7#highlighting-cells
sheet.highlight( ) 이용하니까 제가 원하는 라인 색상 바꾸면서 강조하거나
특정 셀 숨기는 필터링 기능도 활용 가능해 보여서
속도도 빠르고 표시도 1초도 안걸리는걸 보면 treeview 보다는 tksheet가 더 좋을것 같습니다.
예제 코드와 조언 정말 감사 드립니다.
total_line = get_line("log.csv")
time_start = datetime.now()
count_total = 0
index_num = 0;
index_num = len(treeview_list.get_children())
with open("log.csv", "r") as f:
for line in f:
count_total += 1
index_num = index_num + 1
index_str = str(index_num)
time_diff = ((datetime.now() - time_start).total_seconds())
treeitem = [ f"{count_total}/{total_line}",
'%.3f'%time_diff,
f"{line}",
f"{count_total}",
f"{count_total+10}",
f"{count_total+100}",
f"{count_total+1000}",
f"{count_total+10000}",
f"{count_total+100000}",
]
treeview_list.insert('', 'end', text=index_num, iid=index_num, values=treeitem)
treeview_list.yview(index_num)
print(f"count_total = {count_total}, {int(time_diff)} sec")
run_thread();
root.mainloop()
1. 파일 읽기 루프내의 콘솔 출력(print) 제거
2. 파일 읽기 루프내의 treeview_list.get_children()) 제거 (제일 중요)
3. 스레드 호출 제거
이렇게 퍼포먼스는 올릴 수 있는 것 같네요.
조언 정말 감사 드립니다..
GUI 프로그래밍에서 root가 멈춰있는 효과 주지 않으려고 쓰레드로 실행한건데
쓰레드 제거하니까 treeview도 1초만에 6000라인 다 insert 해서 결과 화면 바로 표시해주긴 하네요. ;;
insert 느렸던 이유가 thread.start_new_thread( ) 였던건가봐요. ;;;;
일단 GUI 적으로 먹통되지 않으려면 쓰레드를 써야할듯 한데, 다른 방식 쓰레드를 찾아서 비교 해보고
정 안되면 1초안에 6000라인 다 표시는 그낭하니 쓰레드없이 실행하던지 삽질을 좀 해보겠습니다.
여러가지로 조언 주셔서 개발한당에서 많이 배워갑니다.
조언 주신 분들께 다시 한번 감사 드립니다.