如何在主脚本中从模块中跳出无限循环?

huangapple go评论47阅读模式
英文:

How to break an infinite loop in module from main script?

问题

我正在尝试在我的Python主脚本模块中使用while循环。是否有一种方法可以在不使用多进程的情况下实现这一点?因为我已经看到多进程在模块中不可行,因为Windows不支持fork

所以我正在尝试将while循环放入start_capturemeasure函数中,然后启动measure函数作为进程(如果需要),这样看起来可能是这样的:

# mainScript.py
from sensorHandler import SensorHandler
sensors = SensorHandler()
sensors.start_capture()
sensors.stop_capture()

# sensorHandler.py
class SensorHandler():
    def __init__(self):
        self.sensors = []        

    def start_capture(self):
        process = Process(target=measure, args=(self.sensors,))
        process.start()
    
    def stop_capture():
        process.terminate()            

    def measure(sensors):
        while True:
            # 进行操作

或者像这样:

# mainScript.py
from sensorHandler import SensorHandler
sensors = SensorHandler()
sensors.start_capture()
sensors.stop_capture()

# sensorHandler.py
class SensorHandler():
    def __init__(self):
        self.sensors = [] 

    def start_capture(self):
        while something:
            # 进行操作

    def stop_capture():
        something = false

但主要问题是,我希望在主脚本中想要停止测量时能够打破循环。任何建议或帮助将不胜感激。

英文:

I'm trying to have a while loop in my module for a main script Python. Is there a way to do this without using multiprocessing, as I've seen that multiprocessing isn't viable in modules due to Windows not having fork support.

So I'm trying to fit the while loop inside either the start_capture or measure function, and then start the measure function as process (if needed), so that it would look either something like this:

#mainScript.py
from sensorHandler import SensorHandler
sensors = SensorHandler()
sensors.start_capture()
sensors.stop_capture()

#sensorHandler.py
class SensorHandler():
    def __init__ (self):
        self.sensors = []        

    def start_capture(self):
        process = Process(target=measure,args=(self.sensors,))
        process.start()
    
    def stop_capture():
        process.terminate()            

    def measure(sensors):
        while True:
            #do stuff

Or like this:

#mainScript.py
from sensorHandler import SensorHandler
sensors = SensorHandler()
sensors.start_capture()
sensors.stop_capture()

#sensorHandler.py
class SensorHandler():
    def __init__ (self):
        self.sensors = [] 

    def start_capture(self):
        while something:
            #do stuff

    def stop_capture():
        something = false

But the main point is that I want to break the loop from the main script when I want it to stop measuring. Any recommendations or help would be greatly appreciated.

答案1

得分: 0

你可能尝试过使用break语句来退出循环吗?它会像这样:

while True:
    #做一些事情
    break

这将使你退出循环并继续执行其余的代码。
或者,你也可以使用.exit()sys.exit()

英文:

Have you possibly tried a break statement to exit the loop? It would go something like this:

while True:
    #do stuff
    break

This would cause you to leave the loop and continue with the rest of the code.
Alternatively you can use .exit() or sys.exit()

答案2

得分: 0

可以,你仍然可以在Windows中使用多进程。通常情况下,你只需要确保在启动任何在全局范围内执行直接或间接创建子进程的语句的主要脚本中,这些语句都被包含在一个 if __name__ == '__main__': 块中。还建议将不需要用于初始化任何子进程的全局范围内的语句也放在这样的块中。

但是,在 sensorHandler.py 中还有其他问题。首先,在 stop_capturemeasure 方法中,你没有使用名称为 self 的必需参数。其次,在 SensorHandler 类中的 self.sensors 是一个常规的 list 实例(可能命名不当)。当创建子进程并向该列表添加内容时,它是添加到了位于为子进程创建的新地址空间中的 SensorHandler 实例的副本。因此,按照当前的编码方式,主程序无法检索到此列表。一种解决方法是使用受管理的列表,可以跨进程共享。但要注意,对该列表的每个操作都比使用常规列表要慢。因此,我建议主进程创建受管理的列表并使用它来实例化 SensorHandler 实例,如下所示:

在你的情况下,mainScript.py 将如下所示:

if __name__ == '__main__':
    from sensorHandler import SensorHandler
    from multiprocessing import Manager

    with Manager() as manager:
        measurements = manager.list()
        sensor_handler = SensorHandler(measurements)
        sensor_handler.start_capture()
        input('Hit enter to stop capturing... ')
        sensor_handler.stop_capture()
        print(measurements)

然后,我会将 sensorHandler.py 编码如下:

from multiprocessing import Process
import time

class SensorHandler():
    def __init__ (self, measurements):
        self.measurements = measurements

    def start_capture(self):
        self.process = Process(target=self.measure)
        self.process.start()

    def stop_capture(self):
        self.process.terminate()

    def measure(self):
        for i in range(100):
            self.measurements.append(i)
            time.sleep(1)

在终止几秒钟后打印:

[0, 1, 2]

请注意,我已将属性 sensors 重命名为 measurements,因为你可能是在该列表中添加传感器读数或测量数据,而不是传感器本身。

英文:

Yes, you can still use multiprocessing in Windows. In general, you just need to ensure that within the main script that you are launching any statement at global scope that directly or indirectly executes a statement that creates a child process is wrapped in an if __name__ == '__main__': block. It is also advisable to place in such a block any statement at global scope that is not required for the initialization of any child process.

But you have other issues with sensorHandler.py. First, you do not have required arguments named self in the methods stop_capture and measure. Second, self.sensors in class SensorHandler is a regular list instance (and perhaps not well-named). When the child process is created and presumably appends to this list, it is doing so to a copy of the SensorHandler instance that resides in the new address space created for the child process. So, as currently coded, there is no way for the main program to retrieve this list. One solution is to use a managed list, which is shareable across processes. But be aware that each operation on this list is slower that if you were using a regular list. So I would have the main process create the managed list and use it to instantiate the SensorHandler instance as follows:

In your case, mainScript.py will look like:

if __name__ == '__main__':
    from sensorHandler import SensorHandler
    from multiprocessing import Manager

    with Manager() as manager:
        measurements = manager.list()
        sensor_handler = SensorHandler(measurements)
        sensor_handler.start_capture()
        input('Hit enter to stop capturing... ')
        sensor_handler.stop_capture()
        print(measurements)

Then I would code sensorHandler.py as follows:

from multiprocessing import Process
import time

class SensorHandler():
    def __init__ (self, measurements):
        self.measurements = measurements

    def start_capture(self):
        self.process = Process(target=self.measure)
        self.process.start()

    def stop_capture(self):
        self.process.terminate()

    def measure(self):
        for i in range(100):
            self.measurements.append(i)
            time.sleep(1)

Prints (when terminated after a few seconds):

[0, 1, 2]

Note that I have renamed attribute sensors to measurements since presumably you are appending to this list sensor readings or measurements and not sensors.

huangapple
  • 本文由 发表于 2023年6月19日 22:28:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/76507592.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定