需要 Python 线程编程方面的帮助

发布于 2024-11-06 16:21:53 字数 1126 浏览 2 评论 0原文

我正在开发一个 UI,它有一个运行按钮来在命令提示符下运行某些测试。我尝试在此处实现线程以调用命令提示符并考虑监视线程。在测试运行(在命令提示符下)之前,我希望禁用运行按钮,并且仅在命令提示符关闭时才启用它。

我创建了一个 .bat 文件来在命令提示符中运行测试列表。

代码如下:

用于调用命令提示符的线程:

class RunMonitor(threading.Thread):
def run(self):
    print 'Invoking the command prompt .....'
    subprocess.call(["start", "/DC:\\Scripts", "scripts_to_execute.bat"], shell=True)

用于监视线程

def runscript(self):
    print 'Complete_file_Path inside Run script is : ' , self.complete_file_path
    file_operation.Generate_Bat_File(self.complete_file_path)

    run_monitor_object = RunMonitor()
    run_monitor_object.start()

    while True:
        if run_monitor_object.isAlive():
            print 'The thread is still alive....'
        else:
            print 'The Thread is not alive anymore'
            self.run_button.setEnabled(True)
            break

从上面的示例中,一旦我调用命令提示符,我就会运行一个 while 循环来监视状态,并且我希望该线程只要长时间处于活动状态因为命令提示符被调用,并且一旦我关闭命令提示符就会死掉。但就我而言,应用程序只是挂起......

几个问题: 1. 这是调用线程的正确方法吗? 2. 这是监视线程状态的正确方法吗? 3.有没有更好的方法来处理这个问题?

对此的任何帮助将不胜感激。

谢谢。

I'm developing a UI which has a Run button to run a certain tests on command prompt.I tried implementing threads here for invoking the command prompt and thought of monitoring the thread. Till the tests are run (on command prompt), I want the run button to be disabled and want to enable it only when the command prompt is closed.

I have created a .bat file to run the list of tests in command prompt.

The code is as follows:

Thread for invoking command prompt:

class RunMonitor(threading.Thread):
def run(self):
    print 'Invoking the command prompt .....'
    subprocess.call(["start", "/DC:\\Scripts", "scripts_to_execute.bat"], shell=True)

For Monitoring the thread

def runscript(self):
    print 'Complete_file_Path inside Run script is : ' , self.complete_file_path
    file_operation.Generate_Bat_File(self.complete_file_path)

    run_monitor_object = RunMonitor()
    run_monitor_object.start()

    while True:
        if run_monitor_object.isAlive():
            print 'The thread is still alive....'
        else:
            print 'The Thread is not alive anymore'
            self.run_button.setEnabled(True)
            break

From the above example, as soon as i invoke the command prompt, I run a while loop to monitor the status and I expect that the thread would be active as long as the command prompt is invoked and would be dead once I close the command prompt. But in my case, the application just hangs..

Few questions:
1. is this the right way to invoke thread?
2. is this the right way to monitor the status of the thread?
3. is there a better way of handling this ??

Any help towards this would be greatly appreciated.

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

白昼 2024-11-13 16:21:53

我几乎建议不要使用线程,但是,如果您仍然想这样做,主程序和线程之间通信的一种非常简单的方法是通过线程事件。这实际上只是一个布尔事件(打开或关闭),您可以在设置事件时采取操作。这是您的原始程序更新为使用此:

class RunMonitor(threading.Thread): 
    def __init__(self, quit_event):
        threading.Thread.__init__(self)
        self.quit_event = quit_event
    def run(self):     
        print 'Invoking the command prompt .....'     
        subprocess.call(["start", "/DC:\\Scripts", "scripts_to_execute.bat"], shell=True)
        self.quit_event.set()

def runscript(self):     
    print 'Complete_file_Path inside Run script is : ' , self.complete_file_path     
    file_operation.Generate_Bat_File(self.complete_file_path)      

    quit_event = threading.Event()
    run_monitor_object = RunMonitor(quit_event).start()

    while True:         
        if not quit_event.is_set():
             print 'The thread is still alive....'         
        else:
             print 'The Thread is not alive anymore'             
             self.run_button.setEnabled(True)             
             break 

因此,本质上,在启动线程之前,您创建一个 threading.Event() 对象并将其传递给您的线程。创建此事件后,您可以.set() 它来“打开”该事件,主程序只需等待该事件发生。

就像我说的,这非常简单,它只是一个布尔事件。如果您需要更复杂的东西,您可以添加更多事件,或使用 threading.Queue() 代替。

[编辑] 这是我创建的完整工作示例(而不是尝试将所有内容都塞进示例中):

这是 python 文件,请注意对 subprocess.call< 的更改/code> 行:

import threading
import subprocess
import time

class RunMonitor(threading.Thread): 
    def __init__(self, quit_event):
        threading.Thread.__init__(self)
        self.quit_event = quit_event
    def run(self):     
        print 'Invoking the command prompt .....\n'   
        subprocess.call(["start", "/WAIT", "/DC:\\python27\\sample", "xxx12.bat"], shell=True)                
        self.quit_event.set()

class Something:
    def runscript(self):     
        print 'Starting the thread...'  

        quit_event = threading.Event()
        run_monitor_object = RunMonitor(quit_event).start()

        while True:         
            if not quit_event.is_set():
                 print 'The thread is still alive....'         
            else:
                 print 'The Thread is not alive anymore'             
                 break 
            time.sleep(1)

runme = Something()
runme.runscript()

请注意,我已在主循环中添加了睡眠,以便控制台不会填满“线程仍处于活动状态...”消息。

另外,这里供参考的是我的批处理文件(我将其命名为 xxx12.bat,如 python 代码中所引用),我只是用它来引起延迟,以便我可以证明线程正确终止:

echo wscript.sleep 2500 > xxx12.vbs
start /wait xxx12.vbs
dir c:\
start /wait xxx12.vbs
dir c:\
start /wait xxx12.vbs
dir c:\
start /wait xxx12.vbs
dir c:\
start /wait xxx12.vbs
dir c:\
exit

这里需要注意的重要一点是这个批处理文件中的“exit”命令至关重要,如果我们不将其放在那里,子进程调用将永远不会终止。希望这个例子能有所帮助。

I would almost recommend not using thread, however, if you still want to do that, one very simple way to communicate between your main program and your thread is via threading events. This is really just a boolean event (on or off), and you can take action when the Event is set. Here is your original program updated to use this:

class RunMonitor(threading.Thread): 
    def __init__(self, quit_event):
        threading.Thread.__init__(self)
        self.quit_event = quit_event
    def run(self):     
        print 'Invoking the command prompt .....'     
        subprocess.call(["start", "/DC:\\Scripts", "scripts_to_execute.bat"], shell=True)
        self.quit_event.set()

def runscript(self):     
    print 'Complete_file_Path inside Run script is : ' , self.complete_file_path     
    file_operation.Generate_Bat_File(self.complete_file_path)      

    quit_event = threading.Event()
    run_monitor_object = RunMonitor(quit_event).start()

    while True:         
        if not quit_event.is_set():
             print 'The thread is still alive....'         
        else:
             print 'The Thread is not alive anymore'             
             self.run_button.setEnabled(True)             
             break 

So, essentially, before you start the thread you create a threading.Event() object and pass that to your thread. Once this event is created you can .set() it to 'turn on' the Event, the main program simply waits for that to happen.

Like I say, this is very simple, it's just a boolean event. If you need something more complex you could add more events, or use a threading.Queue() instead.

[EDIT] Here is the fully working sample I created (rather than try to shoe-horn everything into your sample):

Here is the python file, note the changed to the subprocess.call line:

import threading
import subprocess
import time

class RunMonitor(threading.Thread): 
    def __init__(self, quit_event):
        threading.Thread.__init__(self)
        self.quit_event = quit_event
    def run(self):     
        print 'Invoking the command prompt .....\n'   
        subprocess.call(["start", "/WAIT", "/DC:\\python27\\sample", "xxx12.bat"], shell=True)                
        self.quit_event.set()

class Something:
    def runscript(self):     
        print 'Starting the thread...'  

        quit_event = threading.Event()
        run_monitor_object = RunMonitor(quit_event).start()

        while True:         
            if not quit_event.is_set():
                 print 'The thread is still alive....'         
            else:
                 print 'The Thread is not alive anymore'             
                 break 
            time.sleep(1)

runme = Something()
runme.runscript()

Note that I've added a sleep to the main loop so that the console doesn't fill up with "The thread is still alive..." messages.

Also, for reference here is my batch file (I named it xxx12.bat, as referenced in the python code), I just used this to cause delays so I could prove the thread was terminating correctly:

echo wscript.sleep 2500 > xxx12.vbs
start /wait xxx12.vbs
dir c:\
start /wait xxx12.vbs
dir c:\
start /wait xxx12.vbs
dir c:\
start /wait xxx12.vbs
dir c:\
start /wait xxx12.vbs
dir c:\
exit

The important thing to note here is that the 'exit' command in this batch file is vital, if we don't put that there the subprocess call will never terminate. Hopefully this example will help.

顾冷 2024-11-13 16:21:53

问题是你如何监控线程。只要线程处于活动状态,runscript 就会通过循环执行来阻止程序,从而阻止 GUI 事件系统处理用户事件 - 这会导致您遇到“挂起”的情况。

GUI 编程中有许多与线程交互的技术,特别是 PyQt。在这种情况下我更喜欢使用计时器。启动工作线程后,还要创建一个计时器,每隔 100 毫秒左右调用一个方法(槽)。此计时器方法执行监视 - 检查工作线程是否仍处于活动状态等。由于显而易见的原因,这不会阻止事件循环。

The problem is how you're monitoring the thread. runscript blocks the program by executing in a loop as long as the thread is alive, thus blocking the GUI event system from processing user events - this creates the appearance of "hanging" you're experiencing.

There are many techniques for interacting with threads in GUI programming and PyQt in particular. The one I prefer in cases like this is using a timer. Once you start the work thread, also create a timer that invokes a method (slot) every 100 ms or so. This timer method does the monitoring - check if the work thread is still alive, etc. This won't block the event loop, for obvious reasons.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文