【问题标题】:Sequentially running an external independent process using Tkinter and python使用 Tkinter 和 python 顺序运行外部独立进程
【发布时间】:2012-11-08 03:31:41
【问题描述】:

背景:
*我正在使用 Tkinter(便携式 PYscripter,python v2.7.3)创建一个批量模拟作业选择器 + 调度器
*此程序将用作商业求解程序的前端
*程序需要允许用户依次选择一堆文件来模拟,一个接一个。
*它还需要能够从现有/正在运行的作业列表中修改(添加/删除)作业。
*每次模拟肯定会运行几个小时。
*模拟的输出将在单独的程序上查看,我不需要任何管道连接到输出。需要时,将从 GUI 调用外部查看器。

***我有一个主 GUI 窗口,它允许用户:
选择作业文件,提交作业,查看提交日志,停止运行作业(一一)
以上效果很好。

问题:
*如果我使用 subprocess.Popen("command") :所有模拟输入文件同时启动。它必须是连续的(由于许可证和内存限制)

*如果我使用 subprocess.call(" ") 或 wait() 方法,那么 GUI 挂起并且没有范围来停止/添加/修改作业列表。即使“作业提交”命令在独立窗口上,两个父窗口也会挂起,直到作业完成。

问题 1:
*如何按顺序启动模拟作业(如 subprocess.call)并允许主 GUI 窗口运行以修改作业列表或停止作业?
这些作业在一个列表中,使用“askopenfilenames”获取,然后使用 For 循环运行。

守则的相关部分:

cfx5solvepath=r"c:\XXXX"
def file_chooser_default(): 
    global flist1
    flist1=askopenfilename(parent = root2, filetypes =[('.def', '*.def'),('All', '*.*'),('.res', '*.res')], title ="Select Simulation run files...", multiple = True)[1:-1].split('} {')

def ext_process():
    o=list(flist1)
    p=list(flist1)
    q=list(flist1)
    i=0
    while i < len(flist1):
        p[i]='"%s" -def "%s"'%(cfx5solvepath,flist1[i])
        i+=1
    i=0
    while i < len(p):
        q[i]=subprocess.call(p[i])
        i+=1

root2 = Tk()
root2.minsize(300,300)
root2.geometry("500x300")
root2.title("NEW WINDOW")
frame21=Frame(root2, borderwidth=3, relief="solid").pack()
w21= Button(root2,fg="blue", text="Choose files to submit",command=file_chooser_default).pack()
w2a1=Button(root2,fg="white", text= 'Display chosen file names and order', command=lambda:print_var(flist1)).pack()
w2b1= Button (root2,fg="white", bg="red", text="S U B M I T", command=ext_process).pack()
root2.mainloop()

如果您还有其他需要,请告诉我。期待您的帮助。

*编辑 *
在合并@Tim 建议的更改时,GUI 是免费的。由于有一个与主求解程序关联的特定子程序来停止作业,因此我可以使用正确的命令来停止作业。

一旦当前运行的作业停止,列表中的下一个作业会自动启动,正如我所希望的那样。

这是用于停止作业的代码:

def  stop_select(): #Choose the currently running files which are to be stopped
    global flist3
    flist3=askdirectory().split('} {')

def sim_stop(): #STOP the chosen simulation
    st=list(flist3)
    os.chdir("%s"%flist3[0])
    st= subprocess.call('"%s" -directory "%s"'%(defcfx5stoppath,flist3[0]))
    ret1=tkMessageBox.showinfo("INFO","Chosen simulation stopped successfully")
    os.chdir("%s" %currentwd)



问题 2: *一旦上述作业完成,使用 start_new_thread,GUI 不会响应。 GUI 在作业在后台运行时工作。但是start_new_thread 文档说当函数返回时线程应该静默退出。

*另外,我有一个 HTML 日志文件,在每个作业完成时都会写入/更新。当我使用 start_new_thread 时,日志文件内容只有在所有作业完成后才可见。然而,内容以及时间戳是正确的。在不使用 start_new_thread 的情况下,我能够刷新 HTML 文件以获取更新的提交日志。

***使用任务管理器多次退出GUI程序后,突然无法使用start_new_thread函数!!我也尝试过重新安装 PYscripter 并重新启动计算机。我无法从回溯中找出任何合理的信息,即:

Traceback (most recent call last):
File "<string>", line 532, in write
File "C:\Portable Python 2.7.3.1\App\lib\site-packages\rpyc\core\protocol.py", line 439, in _async_request
seq = self._send_request(handler, args)
File "C:\Portable Python 2.7.3.1\App\lib\site-packages\rpyc\core\protocol.py", line 229, in _send_request
self._send(consts.MSG_REQUEST, seq, (handler, self._box(args)))
File "C:\Portable Python 2.7.3.1\App\lib\site-packages\rpyc\core\protocol.py", line 244, in _box
if brine.dumpable(obj):
File "C:\Portable Python 2.7.3.1\App\lib\site-packages\rpyc\core\brine.py", line 369, in dumpable
return all(dumpable(item) for item in obj)
File "C:\Portable Python 2.7.3.1\App\lib\site-packages\rpyc\core\brine.py", line 369, in <genexpr>
return all(dumpable(item) for item in obj)
File "C:\Portable Python 2.7.3.1\App\lib\site-packages\rpyc\core\brine.py", line 369, in dumpable
return all(dumpable(item) for item in obj)
File "C:\Portable Python 2.7.3.1\App\lib\site-packages\rpyc\core\brine.py", line 369, in <genexpr>
return all(dumpable(item) for item in obj)
File "C:\Portable Python 2.7.3.1\App\Python_Working_folder\v350.py", line 138, in ext_process
q[i]=subprocess.call(p[i])
File "C:\Portable Python 2.7.3.1\App\lib\subprocess.py", line 493, in call
return Popen(*popenargs, **kwargs).wait()
File "C:\Portable Python 2.7.3.1\App\lib\subprocess.py", line 679, in __init__
errread, errwrite)
File "C:\Portable Python 2.7.3.1\App\lib\subprocess.py", line 896, in _execute_child
startupinfo)
WindowsError: [Error 2] The system cannot find the file specified

【问题讨论】:

    标签: python tkinter subprocess


    【解决方案1】:

    我建议使用单独的线程来启动作业。最简单的方法是使用 thread 模块中的 start_new_thread 方法。

    将提交按钮的命令改为command=lambda:thread.start_new_thread(ext_process, ())

    您可能希望在单击按钮时禁用它,并在启动完成时启用它。这可以在ext_process 内完成。

    如果您想允许用户取消作业,它会变得更加复杂。此解决方案无法处理。

    【讨论】:

    • @Shreyas:没问题。你还有什么需要回答的吗?如果没有,并且您对此答案感到满意,请accept it
    • :我刚刚注意到,GUI程序在进程完成后挂起!
    猜你喜欢
    • 2014-03-15
    • 1970-01-01
    • 2011-11-03
    • 2016-02-04
    • 2018-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-14
    相关资源
    最近更新 更多