国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專(zhuān)欄INFORMATION COLUMN

Python 中 Ctrl+C 不能終止 Multiprocessing Pool 的解決方案

lmxdawn / 3434人閱讀

摘要:解決方法有兩種。代碼然而這段代碼只有在運(yùn)行在處的時(shí)候才能用中斷,即前你按有效,一旦后則完全無(wú)效建議先確認(rèn)是否真的需要用到多進(jìn)程,如果是多的程序建議用多線(xiàn)程或協(xié)程,計(jì)算特別多則用多進(jìn)程。

本文理論上對(duì)multiprocessing.dummy的Pool同樣有效。

python2.x中multiprocessing提供的基于函數(shù)進(jìn)程池,join后陷入內(nèi)核態(tài),按下ctrl+c不能停止所有的進(jìn)程并退出。即必須ctrl+z后找到殘留的子進(jìn)程,把它們干掉。先看一段ctrl+c無(wú)效的代碼:

#!/usr/bin/env python
import multiprocessing
import os
import time


def do_work(x):
    print "Work Started: %s" % os.getpid()
    time.sleep(10)
    return x * x


def main():
    pool = multiprocessing.Pool(4)
    try:
        result = pool.map_async(do_work, range(8))
        pool.close()
        pool.join()
        print result
    except KeyboardInterrupt:
        print "parent received control-c"
        pool.terminate()
        pool.join()
 

if __name__ == "__main__":
    main()

這段代碼運(yùn)行后,按^c一個(gè)進(jìn)程也殺不掉,最后會(huì)殘留包括主進(jìn)程在內(nèi)共5個(gè)進(jìn)程(1+4),kill掉主進(jìn)程能讓其全部退出。很明顯,使用進(jìn)程池時(shí)KeyboardInterrupt不能被進(jìn)程捕捉。解決方法有兩種。

方案一

下面這段是python源碼里multiprocessing下的pool.py中的一段,ApplyResult就是Pool用來(lái)保存函數(shù)運(yùn)行結(jié)果的類(lèi)

class ApplyResult(object):

    def __init__(self, cache, callback):
        self._cond = threading.Condition(threading.Lock())
        self._job = job_counter.next()
        self._cache = cache
        self._ready = False
        self._callback = callback
        cache[self._job] = self

而下面這段代碼也是^c無(wú)效的代碼

if __name__ == "__main__":
    import threading

    cond = threading.Condition(threading.Lock())
    cond.acquire()
    cond.wait()
    print "done"

很明顯,threading.Condition(threading.Lock())對(duì)象無(wú)法接收KeyboardInterrupt,但稍微修改一下,給cond.wait()一個(gè)timeout參數(shù)即可,這個(gè)timeout可以在map_async后用get傳遞,把

result = pool.map_async(do_work, range(4))

改為

result = pool.map_async(do_work, range(4)).get(1)

就能成功接收^c了,get里面填1填99999還是0xffff都行

方案二

另一種方法當(dāng)然就是自己寫(xiě)進(jìn)程池了,需要使用隊(duì)列,貼一段代碼感受下

#!/usr/bin/env python
import multiprocessing, os, signal, time, Queue

def do_work():
    print "Work Started: %d" % os.getpid()
    time.sleep(2)
    return "Success"

def manual_function(job_queue, result_queue):
    signal.signal(signal.SIGINT, signal.SIG_IGN)
    while not job_queue.empty():
        try:
            job = job_queue.get(block=False)
            result_queue.put(do_work())
        except Queue.Empty:
            pass
        #except KeyboardInterrupt: pass

def main():
    job_queue = multiprocessing.Queue()
    result_queue = multiprocessing.Queue()

    for i in range(6):
        job_queue.put(None)

    workers = []
    for i in range(3):
        tmp = multiprocessing.Process(target=manual_function,
                                      args=(job_queue, result_queue))
        tmp.start()
        workers.append(tmp)

    try:
        for worker in workers:
            worker.join()
    except KeyboardInterrupt:
        print "parent received ctrl-c"
        for worker in workers:
            worker.terminate()
            worker.join()

    while not result_queue.empty():
        print result_queue.get(block=False)

if __name__ == "__main__":
    main()
方案三

使用一個(gè)全局變量eflag作標(biāo)識(shí),讓SIG_INT信號(hào)綁定一個(gè)處理函數(shù),在其中對(duì)eflag的值更改,線(xiàn)程的函數(shù)中以eflag的值判定作為while的條件,把語(yǔ)句寫(xiě)在循環(huán)里,老實(shí)說(shuō)這個(gè)方案雖然可以用,但是簡(jiǎn)直太差勁。線(xiàn)程肯定是可行的,進(jìn)程應(yīng)該還需要多帶帶共享變量,非常不推薦的方式

常見(jiàn)的錯(cuò)誤方案

這個(gè)必須要提一下,我發(fā)現(xiàn)segmentfault上都有人被誤導(dǎo)了

理論上,在Pool初始化時(shí)傳遞一個(gè)initializer函數(shù),讓子進(jìn)程忽略SIGINT信號(hào),也就是^c,然后Pool進(jìn)行terminate處理。代碼

#!/usr/bin/env python
import multiprocessing
import os
import signal
import time


def init_worker():
    signal.signal(signal.SIGINT, signal.SIG_IGN)


def run_worker(x):
    print "child: %s" % os.getpid()
    time.sleep(20)
    return x * x


def main():
    pool = multiprocessing.Pool(4, init_worker)
    try:
        results = []
        print "Starting jobs"
        for x in range(8):
            results.append(pool.apply_async(run_worker, args=(x,)))

        time.sleep(5)
        pool.close()
        pool.join()
        print [x.get() for x in results]
    except KeyboardInterrupt:
        print "Caught KeyboardInterrupt, terminating workers"
        pool.terminate()
        pool.join()


if __name__ == "__main__":
    main()

然而這段代碼只有在運(yùn)行在time.sleep(5)處的時(shí)候才能用ctrl+c中斷,即前5s你按^c有效,一旦pool.join()后則完全無(wú)效!

建議

先確認(rèn)是否真的需要用到多進(jìn)程,如果是IO多的程序建議用多線(xiàn)程或協(xié)程,計(jì)算特別多則用多進(jìn)程。如果非要用多進(jìn)程,可以利用Python3的concurrent.futures包(python2.x也能裝),編寫(xiě)更加簡(jiǎn)單易用的多線(xiàn)程/多進(jìn)程代碼,其使用和Java的concurrent框架有些相似.
經(jīng)過(guò)親自驗(yàn)證,ProcessPoolExecutor是沒(méi)有^c的問(wèn)題的,要用多進(jìn)程建議使用它

參考

http://bryceboe.com/2010/08/26/python-multiprocessing-and-keyboardinterrupt/#georges

http://stackoverflow.com/questions/1408356/keyboard-interrupts-with-pythons-multiprocessing-pool#comment12678760_6191991

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/37677.html

相關(guān)文章

  • python進(jìn)階筆記【1】--- 多進(jìn)程

    摘要:很簡(jiǎn)單,這個(gè)模塊實(shí)現(xiàn)了開(kāi)辟一塊共享內(nèi)存空間,就好比中的方法一樣,有興趣的同學(xué)可以去查閱。查了下資料,返回的對(duì)象控制了一個(gè)進(jìn)程,可用于多進(jìn)程之間的安全通信,其支持的類(lèi)型有和等。 有關(guān)于 multiprocessing 中共享變量的問(wèn)題 現(xiàn)在的cpu都很強(qiáng)大,比方我用的至強(qiáng)2620有24核可以同時(shí)工作,并行執(zhí)行進(jìn)程程序。這在計(jì)算密集型的程序是很需要的,如沙漠中的綠洲,令人重獲新生。那么,問(wèn)...

    Wildcard 評(píng)論0 收藏0
  • Python 面試」第三次更新

    摘要:說(shuō)一下進(jìn)程線(xiàn)程以及多任務(wù)多進(jìn)程多線(xiàn)程和協(xié)程進(jìn)程概念一個(gè)程序?qū)?yīng)一個(gè)進(jìn)程,這個(gè)進(jìn)程被叫做主進(jìn)程,而一個(gè)主進(jìn)程下面還有許多子進(jìn)程。避免了由于系統(tǒng)在處理多進(jìn)程或者多線(xiàn)程時(shí),切換任務(wù)時(shí)需要的等待時(shí)間。 showImg(https://segmentfault.com/img/bVbuYxg?w=3484&h=2480); 閱讀本文大約需要 10 分鐘。 14.說(shuō)一下進(jìn)程、線(xiàn)程、以及多任務(wù)(多進(jìn)...

    wslongchen 評(píng)論0 收藏0
  • python綜合學(xué)習(xí)二之多進(jìn)程

    摘要:本節(jié)講學(xué)習(xí)的多進(jìn)程。和之前的的不同點(diǎn)是丟向的函數(shù)有返回值,而的沒(méi)有返回值。所以接下來(lái)讓我們來(lái)看下這兩個(gè)進(jìn)程是否會(huì)出現(xiàn)沖突。 本節(jié)講學(xué)習(xí)Python的多進(jìn)程。 一、多進(jìn)程和多線(xiàn)程比較 多進(jìn)程 Multiprocessing 和多線(xiàn)程 threading 類(lèi)似, 他們都是在 python 中用來(lái)并行運(yùn)算的. 不過(guò)既然有了 threading, 為什么 Python 還要出一個(gè) multip...

    gityuan 評(píng)論0 收藏0
  • Python_系統(tǒng)編程

    摘要:主進(jìn)程會(huì)等待所有的子進(jìn)程先結(jié)束,然后再結(jié)束主進(jìn)程。關(guān)閉進(jìn)程池,關(guān)閉后實(shí)例不再接收新的請(qǐng)求等待實(shí)例中的所有子進(jìn)程執(zhí)行完畢,主進(jìn)程才會(huì)退出,必須放在語(yǔ)句之后。主進(jìn)程一般都用來(lái)等待,任務(wù)在子進(jìn)程中執(zhí)行。 多任務(wù):同一個(gè)時(shí)間段中,執(zhí)行多個(gè)函數(shù)/運(yùn)行多個(gè)程序. 操作系統(tǒng)可以同時(shí)運(yùn)行多個(gè)任務(wù):操作系統(tǒng)輪流讓各個(gè)任務(wù)交替執(zhí)行,任務(wù)1執(zhí)行0.01秒,切換到任務(wù)2,任務(wù)2執(zhí)行0.01秒,再切換到任務(wù)3,...

    wuaiqiu 評(píng)論0 收藏0
  • python簡(jiǎn)單好用進(jìn)程間數(shù)據(jù)通訊模塊multiprocessing.Manager

    摘要:目前開(kāi)發(fā)中有遇到進(jìn)程間需要共享數(shù)據(jù)的情況所以研究了下主要會(huì)以為例子說(shuō)明下進(jìn)程間共享同一個(gè)父進(jìn)程使用說(shuō)明創(chuàng)建一個(gè)對(duì)象創(chuàng)建一個(gè)創(chuàng)建一個(gè)測(cè)試程序創(chuàng)建進(jìn)程池進(jìn)行測(cè)試簡(jiǎn)單的源碼分析這時(shí)我們?cè)倏匆粋€(gè)例子創(chuàng)建一個(gè)對(duì)象創(chuàng)建一個(gè)創(chuàng)建一個(gè)測(cè)試程序創(chuàng)建進(jìn)程池進(jìn)行 目前開(kāi)發(fā)中有遇到進(jìn)程間需要共享數(shù)據(jù)的情況. 所以研究了下multiprocessing.Manager, 主要會(huì)以dict為例子, 說(shuō)明下進(jìn)程間共...

    jeyhan 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<