问题描述
我正在尝试编写一个程序,列出文件夹中所有 .xml 文件的列表,然后将它们复制到另一个目录并从原始目录中删除.程序的这部分工作正常.我想这样做,以便我可以单击 GUI 中的按钮并让它扫描和处理文件夹,直到我按下按钮将其关闭.同样,打开它不是问题,但试图阻止它让我难倒.我希望它在中间等待一段时间,但使用 time.sleep(x) 会冻结整个程序,并且在它停止睡眠之前不允许我输入更多命令,只是为了让它处理然后再次睡眠.关于如何从 GUI tkinter 按钮基本上启动/停止 while 循环的任何建议?
I'm trying to write a program that makes a list of all .xml files in a folder, then copies them to another directory and deletes from the original directory. This part of the program works fine. I want to make it so that I can click a button in the GUI and have it scan and process folders until I press a button to turn it off. Again, turning it on is not a problem, but trying to stop it has me stumped. I'd like it to wait some time in between but using time.sleep(x) freezes the entire program and doesn't let me input any more commands until it's stopped sleeping, only for it to process and then sleep again. Any suggestions on how to essentially start/stop a while loop from a GUI tkinter button?
代码如下:
#! python3
import glob
import time
import shutil
import os
import sys
import datetime
import errno
import re
import fnmatch
import tkinter # copy tcl8.5 and tk8.5 to folder
from tkinter import ttk
import sched
flag = 0
with open("config.ini") as f:
g = f.readlines()
sourcedir = g[0][10:-1]
ICdir = g[1][13:-1]
BUdir = g[2][13:-1]
LOGdir = g[3][8:-1]
el = g[4][3:-1]
# reads directories from config.ini
h = len(sourcedir)
# obtains length of address, used later on
def exemel():
m = sorted(glob.glob(sourcedir+"/*.xml"), key=os.path.getmtime)
n = len(m)
if n == 0:
print("none left")
for item in range(n):
try:
m = sorted(glob.glob(sourcedir+"/*.xml"), key=os.path.getmtime)
n = len(m)
if n == 0:
print("none left")
global flag
if flag == 5:
flag = 0
item = item + 1
with FileLock(m[item]):
k = h - len(m[item])
g = m[item][k:]
shutil.copy(m[item], ICdir)
shutil.move(m[item], BUdir)
print(m[item] + " successfully processed.")
dated = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
if os.path.exists(LOGdir):
with open(LOGdir, "a") as logging:
logline = '\n' + '"' + g[1:] + '", #' + dated + "# copied"
logging.write(logline)
else:
with open(LOGdir, "w") as logging:
logline = '"' + g[1:] + '", #' + dated + "# copied"
logging.write(logline)
except PermissionError:
print("File in use, waiting..")
time.sleep(1.5)
flag += 1
continue
except shutil.Error as e:
os.remove(ICdir + g)
os.remove(BUdir + g)
print("Existing files removed..")
dated = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
if el == "1":
if os.path.exists(LOGdir):
with open(LOGdir, "a") as logging:
logline = '\n' + '"' + g[1:] + '", #' + dated + "# overwritten"
logging.write(logline)
else:
with open(LOGdir, "w") as logging:
logline = '"' + g[1:] + '", #' + dated + "# overwritten"
logging.write(logline)
except IndexError:
item = 0
continue
except SystemExit:
break
except KeyboardInterrupt:
break
def prunt():
print("ZES")
def config():
print("config")
def stop():
print("stop")
global x
x = False
global STOP
STOP = True
s = sched.scheduler(time.time, time.sleep)
def run_periodically(start, end, interval, func):
event_time = start
while event_time < end:
s.enterabs(event_time, 0, func, ())
event_time += interval
s.run()
def starter():
run_periodically(time.time(), time.time()+600, 60, exemel)
### GUI BEGIN ###
root = tkinter.Tk()
root.title("XML Wizard")
mainframe = ttk.Frame(root, padding="3 3 12 12")
mainframe.grid(column=0, row=0, sticky=("N","W", "E", "S"))
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)
sourceEntry = ttk.Entry(mainframe, width=50, textvariable=sourcedir)
sourceEntry.grid(column=2, row = 1, columnspan=2)
ttk.Label(mainframe, text="Source Directory:").grid(column=1, row=1, sticky="W")
BackupEntry = ttk.Entry(mainframe, width=50, textvariable=BUdir)
BackupEntry.grid(column=2, row = 2, columnspan=2)
ttk.Label(mainframe, text="Backup Directory:").grid(column=1, row=2, sticky="W")
ImportEntry = ttk.Entry(mainframe, width=50, textvariable=ICdir)
ImportEntry.grid(column=2, row = 3, columnspan=2)
ttk.Label(mainframe, text="Import Directory:").grid(column=1, row=3, sticky="W")
ttk.Button(mainframe, text="Go", command=starter).grid(column=4, row=5, sticky="W")
ttk.Button(mainframe, text="Save Config", command=config).grid(column=5, row=4, sticky="W")
ttk.Button(mainframe, text="Load Config", command=config).grid(column=5, row=3, sticky="W")
ttk.Button(mainframe, text="Stop", command=stop).grid(column=3, row=5, sticky="W")
root.mainloop()
FileLock 函数在此处找到,如果您想知道,它可以完美运行,但为了空间/可读性,我将其省略了.我知道我的代码很草率,但我才刚刚开始编程.
FileLock function was found on here and works perfectly if you're wondering but I left it out for space/readibility. I know my code is sloppy but I've only just begun programming.
非常欢迎任何建议/替代方法!
Any recommendations/alternate methods are very welcome!
顺便说一句:exemel是我要循环的函数!
btw: exemel is the function that I want to loop!
推荐答案
基本思想是有一个处理单个文件的函数,然后使用事件循环重复调用该函数,直到没有更多文件需要处理过程.您可以使用 after
命令执行此操作.
The basic idea is to have a function that processes a single file, and then you use the event loop to call that function repeatedly until there are no more files to process. You do this with the after
command.
在您的函数中,您还可以检查全局标志.如果设置了该标志,则该函数不起作用,并且不会安排任何要完成的工作.使用暂停按钮按钮设置标志.设置完成后,调用一次您的函数,它会继续运行,直到处理完所有文件.
Inside your function you can also check for a global flag. If the flag is set, the function does no work, and doesn't schedule any work to be done. Use your pause button button to set the flag. Once you set this up, call your function once and it will continue to run until all files have been processed.
例如:
def do_one_file():
global files_to_process, paused
if not paused:
file = files_to_process.pop()
... do some work here ...
if len(files_to_process) > 0:
root.after(10, do_one_file)
这将检查您是否已暂停工作.如果您没有,它会从文件堆栈中拉出一个文件来处理和处理它.然后,如果还有更多工作要做,它会安排下一个文件在 10 毫秒内处理.
This will check to see if you've paused the work. If you have not, it will pull one file off of the stack of files to process and process it. Then, if there's more work to be done, it schedules the next file to be processed in 10ms.
假设实际工作只需要几百毫秒,您的 GUI 将保持响应,并且复制在后台"进行.我把它放在引号中是因为这一切都发生在主线程而不是后台线程或进程上,但它发生在 GUI 什么都不做的时候(实际上大部分时间).
Assuming that the actual work takes only a few hundred ms, your GUI will remain responsive and the copying happens "in the background". I put that in quotes because it all happens on the main thread rather than a background thread or process, but it happens in those moments when the GUI is doing nothing else (which is actually most of the time).
这篇关于开始/停止while循环?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!