python - 在 Python3 的线程池中退出无限循环的安全方法

标签 python python-3.x multiprocessing

我正在使用 Python3 模块:

  • 请求 HTTP GET 调用几个粒子光子,这些粒子光子被设置为简单的HTTP 服务器

    /li>
  • 作为客户端,我使用 Raspberry Pi(它也是一个接入点)作为 HTTP 客户端,它使用 multiprocessing.dummy.Pool 来制作HTTP GET请求上述光子

轮询程序如下:

def pollURL(url_of_photon):
    """
    pollURL: Obtain the IP Address and create a URL for HTTP GET Request
    @param: url_of_photon: IP address of the Photon connected to A.P.
    """
    create_request = 'http://' + url_of_photon + ':80'
    while True:
        try:
            time.sleep(0.1) # poll every 100ms
            response = requests.get(create_request)
            if response.status_code == 200:
                # if success then dump the data into a temp dump file
                with open('temp_data_dump', 'a+') as jFile:
                    json.dump(response.json(), jFile)
            else:
               # Currently just break
               break
        except KeyboardInterrupt as e:
            print('KeyboardInterrupt detected ', e)
            break

url_of_photon 值是从 Pi 上可用的 dnsmasq.leases 文件中获取的简单 IPv4 地址

main() 函数:

def main():
    # obtain the IP and MAC addresses from the Lease file
    IP_addresses = []
    MAC_addresses = []
    with open('/var/lib/misc/dnsmasq.leases', 'r') as leases_file:
        # split lines and words to obtain the useful stuff.
        for lines in leases_file:
            fields = lines.strip().split()
            # use logging in future
            print('Photon with MAC: %s has IP address: %s' %(fields[1],fields[2]))
            IP_addresses.append(fields[2])
            MAC_addresses.append(fields[1])

            # Create Thread Pool
            pool = ThreadPool(len(IP_addresses))
            results = pool.map(pollURL, IP_addresses)
            pool.close()
            pool.join()

if __name__ == '__main__':
    main()

问题

程序运行良好,但是当我按下 CTRL + C 时程序不会终止。经过挖掘,我发现这样做的方法是使用 CTRL + \

我如何在我的 pollURL 函数中使用它来安全退出程序,即执行 poll.join() 以便不留下剩余进程?

注意事项:

KeyboardInterrupt 永远不会被函数识别。因此,我在尝试检测 CTRL + \ 时遇到了麻烦。

最佳答案

pollURL 在另一个线程中执行。在 Python 中,信号仅在主线程中处理。因此,SIGINT 只会在主线程中引发 KeyboardInterrupt。

来自signal documentation :

Signals and threads

Python signal handlers are always executed in the main Python thread, even if the signal was received in another thread. This means that signals can’t be used as a means of inter-thread communication. You can use the synchronization primitives from the threading module instead.

Besides, only the main thread is allowed to set a new signal handler.

您可以通过以下方式(伪代码)实现您的解决方案。

event = threading.Event()

def looping_function( ... ):
    while event.is_set():
        do_your_stuff()

def main():
    try:
        event.set()
        pool = ThreadPool()
        pool.map( ... )
    except KeyboardInterrupt:
        event.clear()
    finally:
        pool.close()
        pool.join()

关于python - 在 Python3 的线程池中退出无限循环的安全方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46157530/

相关文章:

python - 无法解析电话号码和地址

python-3.x - 生成具有偶数个 0's and 1' 的给定长度的所有二进制数

python - 为什么在尝试使用 SharedMemoryManager (python 3.8) 替代 BaseManager 时会出现 NameError 错误?

multithreading - 为什么自旋锁会成为多线程程序中的性能问题?

python - 区分消息python3 tcp sockets

python - 如何从同一列中获取所有值?

python - 默认为并选择 Tkinter 列表框中的第一项

python - 打印列表中的列表时遇到问题

python - 具有 5 个数字或 IND/5 个数字的字符串的正则表达式

python - python 3.6 multiprocessing.Pool()开始使用Windows的速度非常慢