4

フォルダ内のすべての .xml ファイルのリストを作成し、それらを別のディレクトリにコピーして元のディレクトリから削除するプログラムを作成しようとしています。プログラムのこの部分は正常に動作します。GUI のボタンをクリックして、ボタンを押してオフにするまでフォルダーをスキャンして処理できるようにしたいと考えています。繰り返しますが、オンにすることは問題ではありませんが、停止しようとすると困惑します. その間しばらく待ちたいのですが、 time.sleep(x) を使用するとプログラム全体がフリーズし、スリープが停止するまでコマンドを入力できなくなり、処理してから再びスリープするだけになります。GUI tkinter ボタンから while ループを本質的に開始/停止する方法に関する提案はありますか?

コードは以下のとおりです。

#! 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 関数は here にあり、不思議に思っているなら完全に機能しますが、スペース/読みやすさのために省略しました。自分のコードがずさんであることはわかっていますが、プログラミングを始めたばかりです。

推奨事項/代替方法は大歓迎です!

ところで: exemel はループしたい関数です!

4

1 に答える 1

3

基本的な考え方は、1 つのファイルを処理する関数を用意し、イベント ループを使用して、処理するファイルがなくなるまでその関数を繰り返し呼び出すことです。コマンドでこれを行いafterます。

関数内で、グローバル フラグを確認することもできます。フラグが設定されている場合、関数は機能せず、実行する作業をスケジュールしません。一時停止ボタン ボタンを使用して、フラグを設定します。これを設定したら、関数を 1 回呼び出すと、すべてのファイルが処理されるまで実行され続けます。

例えば:

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)

これにより、作業を一時停止したかどうかがチェックされます。そうでない場合は、ファイルのスタックから 1 つのファイルを取り出して処理し、処理します。その後、さらに作業が必要な場合は、次のファイルを 10 ミリ秒で処理するようにスケジュールします。

実際の作業に数百ミリ秒しかかからないと仮定すると、GUI は応答性を維持し、コピーは「バックグラウンドで」行われます。バックグラウンド スレッドやプロセスではなくメイン スレッドですべてが発生するため、引用符で囲みますが、GUI が他に何もしていないときに発生します (実際にはほとんどの場合)。

于 2013-09-13T13:44:35.393 に答える