1

내가 시작하는 새 스레드로 컨트롤 c를 보낼 수 있어야합니다. 어떻게 내가 이것에 관해 갈 것이냐. 스레드를 시작할 수는 있지만, 컨트롤을 사용하여 명령 줄에서 멈추어야합니다. c. 당신이 무슨 일을하는지Tkinter 스레딩

from Tkinter import * 
import threading # should use the threading module instead! 
import Queue 
import os 


def show1(): 
    os.system('ola_recorder -p MyRecord -i 0') 

def show2(): 
    os.system('ola_recorder -p MyRecord ') 

def stop(): 
    os.system('^c') 




t = threading.Thread(name='Show2', target=show2) 





root = Tk() 
b = Button(root, text="Show 1", command=lambda: thread.start_new(show1,())) 
b.pack() 

b2 = Button(root, text="Show 2", command=lambda: t.start()) 
b2.pack() 



root.mainloop() 
+1

[Tkinter에서 외부 서브 프로세스를 시작/중지하는 방법에 대한 예제] (https://gist.github.com/zed/4067619). 다음은 [스레드를 사용하여 하위 프로세스의 출력을 읽는 비슷한 예입니다 (https://gist.github.com/zed/42324397516310c86288). – jfs

+0

이 예제를 살펴보면서 스레드 코드를 약간 정리할 수 있었지만 프로세스를 멈출 수는 없습니다. 어떤 아이디어? – user808996

+1

'p = Popen()'을 사용하여 서브 프로세스를 시작하고'p.terminate()'를 사용하여 예제와 같이 중지하십시오. – jfs

답변

4

첫째, 이유는 작동하지 않습니다

os.system를 호출 할 때마다 그냥 브랜드 -을 생성 플랫폼의 system (또는 _system, 일부 Windows 플랫폼) 함수를 호출 매번 새로운 쉘 프로세스. 따라서 os.system을 사용하여 다른 통화에 영향을 줄 수있는 방법이 없습니다. 당신이 임의의 프로세스에^C를 보내려면


, 그 os.kill로 할 수 있습니다.

def send_ctrl_c(pid): 
    try: 
     sig = signal.CTRL_C_EVENT 
    except AttributeError: 
     sig = signal.SIGINT 
    else: 
     os.signal(pid, sig) 

그러나, 당신은 다른 프로세스의 pid는 그렇게 할 필요가 있고, os.system 당신에게 그것을 제공하지 않습니다 : 그것은 휴대용하려면, 당신은 이런 식으로 뭔가를해야한다. 여기에 쉘을 사용하는 좋은 이유가 없기 때문에

proc2 = None 

def show2(): 
    global proc2 
    proc2 = subprocess.Popen('ola_recorder -p MyRecord', shell=True) 
    proc2.wait() 

, 당신은 아마 더 나을 것 Popen 목록을 통과 :


그래서, 옳은 일이 subprocess 모듈을 사용하는 것입니다 문자열 대신 args를 사용하고 shell=True을 남겨 둡니다. 그리고 물론 글로벌에 proc2을 붙이지 않는 것이 훨씬 깔끔할 것입니다,하지만이 장난감 예제에서는 무시할 것입니다.

어쨌든, 지금은 PID를 얻을 사용할 수 있습니다 : 당신이 그것을 할 거라면

def stop(): 
    send_ctrl_c(proc2.pid) 

그러나, 당신은뿐만 아니라 단지 직접 Popen 객체를 사용할 수 있습니다. 당신이 그것으로 무엇을 할 수 있는지의 자세한 내용에 대한 the docs를 참조하지만, 여기에 빠른 버전입니다 : 그것은^C (POSIX)를받은 것처럼

def stop(): 
    global proc2 
    try: 
     sig = signal.CTRL_C_EVENT 
    except AttributeError: 
     sig = signal.SIGINT 
    proc.send_signal(sig) 

당신이 stop 전화

는, 프로세스가 정확히 살해됩니다하거나 가능한 한^C (Windows)를받은 것처럼 가깝게, wait 호출은 (최소한 POSIX에서는 -2로) 리턴 할 것이고 스레드도 끝날 것입니다.


마지막 주 : 직접 thread 모듈을 사용하려면 거의 절대, 당신은 threading.Thread 객체를 다시 사용하고 싶지 않아요.그래서, 대신의 :

b = Button(root, text="Show 1", command=lambda: thread.start_new(show1,())) 

... 나이 :

b2 = Button(root, text="Show 2", command=lambda: t.start()) 

은 ... 이렇게 :

def start2(): 
    global t2 
    t2 = threading.Thread(name='Show2', target=show2) 
    t2.start() 

은 물론, 비 장난감 프로그램은 글로벌을 사용하지 않아야합니다, 마지막 스레드 대신 모든 기존 스레드를 추적하고자 할 것입니다 (백그라운드 스레드가 이미 실행 중일 때 버튼을 클릭 할 수있는 경우). join 모두 필요합니다. 스레드를 종료합니다.

+0

도움에 감사드립니다. 나는 이것으로 많은 것을 배웠다. – user808996