我有一个熊猫操作需要很长时间,因为xlsx文件很大,可以导入到数据框中。我想通知用户,他必须在任务运行时等待,但我无法做到这一点。这是我的功能:
def create_list_of_data():
list_data_all = []
list_files_xlsx_f = create_list_of_xlsx()
for xls_files in list_files_xlsx_f:
df = pandas.read_excel(xls_files)
df = df[["COL1", "COL2"]]
list_data = df.values.tolist()
list_data_all.extend(list_data)
return list_data_all
我尝试的是使用线程:
import itertools
import threading
import time
import sys
#here is the animation
def animate():
for c in itertools.cycle(['|', '/', '-', '\\']):
if done:
break
sys.stdout.write('\rloading ' + c)
sys.stdout.flush()
time.sleep(0.1)
sys.stdout.write('\rDone! ')
def create_list_of_data():
list_data_all = []
list_files_xlsx_f = create_list_of_xlsx()
for xls_files in list_files_xlsx_f:
done = False
t = threading.Thread(target=animate)
t.start()
df = pandas.read_excel(xls_files)
done = True
df = df[["COL1", "COL2"]]
list_data = df.values.tolist()
list_data_all.extend(list_data)
return list_data_all
我的问题是,动画函数无法识别“完成”变量。也许这不是正确的方法。有什么想法吗?
函数create_list_of_data()从另一个的PySide按钮启动 文件。
答案 0 :(得分:1)
如果将布尔值与对象包装在一起,则可以按引用而不是按值传递
import itertools
import threading
import time
import sys
#here is the animation
def animate(holder):
for c in itertools.cycle(['|', '/', '-', '\\']):
if holder.done:
break
sys.stdout.write('\rloading ' + c)
sys.stdout.flush()
time.sleep(0.1)
sys.stdout.write('\rDone! ')
def create_list_of_data():
list_data_all = []
class Holder(object):
done = False
holder = Holder()
t = threading.Thread(target=animate, args=(holder,))
t.start()
time.sleep(10) #Simulating long job
holder.done = True
return list_data_all
我稍微修改了示例,以便无需额外的功能即可运行它。
答案 1 :(得分:1)
您应该在函数外部定义“完成”,以便它是全局变量。这样,两个功能都可以访问它。试试这个:
import itertools
import threading
import time
import sys
done = False
#here is the animation
def animate():
for c in itertools.cycle(['|', '/', '-', '\\']):
if done:
break
sys.stdout.write('\rloading ' + c)
sys.stdout.flush()
time.sleep(0.1)
sys.stdout.write('\rDone! ')
def create_list_of_data():
list_data_all = []
list_files_xlsx_f = create_list_of_xlsx()
for xls_files in list_files_xlsx_f:
done = False
t = threading.Thread(target=animate)
t.start()
df = pandas.read_excel(xls_files)
done = True
df = df[["COL1", "COL2"]]
list_data = df.values.tolist()
list_data_all.extend(list_data)
return list_data_all
答案 2 :(得分:1)
基本上,您需要在其他线程处于活动状态时显示loading *
:
import sys
import time
import itertools
import threading
def long_process():
time.sleep(5)
thread = threading.Thread(target=long_process)
thread.start()
for c in itertools.cycle(['|', '/', '-', '\\']):
sys.stdout.write('\rloading ' + c)
sys.stdout.flush()
time.sleep(0.1)
if not thread.isAlive():
break
sys.stdout.write('\rDone! ')
输出:
答案 3 :(得分:0)
您可以使用多处理而非线程化,并在单独的进程中启动动画和创建函数_create_list_of_data。 这样的事情应该起作用。
import time
import multiprocessing as mp
def countdown(seconds, message):
while seconds:
mins, secs = divmod(int(seconds), 60)
timeformat = '{:02d}:{:02d} '.format(mins, secs)
print(timeformat + message, end='\r')
time.sleep(1)
seconds -= 1
def slowFunction(seconds):
print('Begin')
time.sleep(seconds)
print('Done')
q = mp.Queue()
countdownProcess = mp.Process(target=countdown, args=(10, 'loading...'))
slowProcess = mp.Process(target=slowFunction, args=(10, ))
countdownProcess.start()
slowProcess.start()
countdownProcess.join()
slowProcess.join()
答案 4 :(得分:0)
您可以使用队列将完成的值发送到线程:
import itertools
import threading
from queue import Queue
import time
import sys
#here is the animation
def animate(q):
for c in itertools.cycle(['|', '/', '-', '\\']):
done = q.get()
if done:
break
sys.stdout.write('\rloading ' + c)
sys.stdout.flush()
time.sleep(0.1)
sys.stdout.write('\rDone! ')
def create_list_of_data():
list_data_all = []
list_files_xlsx_f = create_list_of_xlsx()
queue = Queue()
for xls_files in range(1,1000):
done = False
queue.put(done)
t = threading.Thread(target=animate, args=(queue,))
t.start()
df = pandas.read_excel(xls_files)
done = True
queue.put(done)
df = df[["COL1", "COL2"]]
list_data = df.values.tolist()
list_data_all.extend(list_data)
return list_data_all