1

背景:
*Tkinter (Portable PYscripter、python v2.7.3) を使用してバッチ シミュレーション ジョブ セレクター + スケジューラーを作成しています
*このプログラムは商用ソルバー プログラムのフロント エンドとして機能します
*プログラムはユーザーが選択できるようにする必要があります順番に、次々とシミュレートするファイルの束。
*既存/実行中のジョブ リストからジョブを変更 (追加/削除) する機能も必要です。
*各シミュレーションは確実に数時間実行されます。
*シミュレーションの出力は別のプログラムで表示され、出力へのパイプは必要ありません。外部ビューアーは、必要に応じて GUI から呼び出されます。

***メインの GUI ウィンドウがあり、ユーザーは次のことを実行できます:
ジョブ ファイルの選択、ジョブの送信、送信ログの表示、実行中のジョブの停止 (1 つずつ)
上記はうまく機能します。

問題:
*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
4

1 に答える 1

0

ジョブの起動には別のスレッドを使用することをお勧めします。最も簡単な方法は、モジュールのstart_new_threadメソッドを使用することです。thread

送信ボタンのコマンドを次のように変更しますcommand=lambda:thread.start_new_thread(ext_process, ())

おそらく、クリックされたときにボタンを無効にし、起動が完了したら有効にすることをお勧めします。これは 内で行うことができますext_process

ユーザーがジョブをキャンセルできるようにしたい場合は、さらに複雑になります。このソリューションはそれを処理しません。

于 2012-11-20T06:04:44.943 に答える