문제

어떻게 관리할 수 있 KeyboardInterrupt 이벤트 파이썬의 최적화를 하는 c 컴파일러 풀?여기에 간단한 예제:

from multiprocessing import Pool
from time import sleep
from sys import exit

def slowly_square(i):
    sleep(1)
    return i*i

def go():
    pool = Pool(8)
    try:
        results = pool.map(slowly_square, range(40))
    except KeyboardInterrupt:
        # **** THIS PART NEVER EXECUTES. ****
        pool.terminate()
        print "You cancelled the program!"
        sys.exit(1)
    print "\nFinally, here are the results: ", results

if __name__ == "__main__":
    go()

실행하는 경우 위 코드 KeyboardInterrupt 가져오기 때 나를 누르 ^C, 이지만,프로세스 단순히 중단에서는 점이다 외부에서.

할 수 있을 누르 ^C 언제든지 원인의 모든 프로세스를 정상적으로 종료.

도움이 되었습니까?

해결책

이것이 버그가 있습니다.때를 기다리는 상태에서 threading.상태입니다.wait(),KeyboardInterrupt 전송되지 않습니다.Repro:

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

이 KeyboardInterrupt 예외 없이 전달될 때까지 기다릴()반환,그리고 그것은 반환되지 않는,그래서 인터럽트 발생하지 않습니다.KeyboardInterrupt 해 거의 확실하게 인터럽트 조건이 기다립니다.

참고로 이 발생하지 않는 경우 제한 시간은 지정cond.기(1)을 받을 것이 중단 immediately.그래서 해결을 지정한다.그렇게 교체

    results = pool.map(slowly_square, range(40))

    results = pool.map_async(slowly_square, range(40)).get(9999999)

또는 이와 유사한.

다른 팁

에서 무엇을 나는 최근에 발견해,최고의 솔루션을 설정하는 작업자 프로세스를 무시하 SIGINT 모두고 제한 모든 정리 코드가 부모 프로세스.이 문제를 해결하 모두에 대한 유휴 상태이고 바쁜 작업자 프로세스,그리고 필요 없는 오류 처리 코드에 당신의 자식 프로세스입니다.

import signal

...

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

...

def main()
    pool = multiprocessing.Pool(size, init_worker)

    ...

    except KeyboardInterrupt:
        pool.terminate()
        pool.join()

설명과는 전체 예제 코드에서 찾을 수 있습니다 http://noswap.com/blog/python-multiprocessing-keyboardinterrupt/http://github.com/jreese/multiprocessing-keyboardinterrupt 각각합니다.

몇 가지 이유만의 예외는 상속에서 기지 Exception 클래스를 처리합니다.문제 해결 방법으로,다시 수상 KeyboardInterruptException 인스턴스:

from multiprocessing import Pool
import time

class KeyboardInterruptError(Exception): pass

def f(x):
    try:
        time.sleep(x)
        return x
    except KeyboardInterrupt:
        raise KeyboardInterruptError()

def main():
    p = Pool(processes=4)
    try:
        print 'starting the pool map'
        print p.map(f, range(10))
        p.close()
        print 'pool map complete'
    except KeyboardInterrupt:
        print 'got ^C while pool mapping, terminating the pool'
        p.terminate()
        print 'pool is terminated'
    except Exception, e:
        print 'got exception: %r, terminating the pool' % (e,)
        p.terminate()
        print 'pool is terminated'
    finally:
        print 'joining pool processes'
        p.join()
        print 'join complete'
    print 'the end'

if __name__ == '__main__':
    main()

일반적으로 당신을 얻을 것입되는 출력은 다음과 같습니다.

staring the pool map
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
pool map complete
joining pool processes
join complete
the end

그래서 만약 당신 ^C, 을 얻을 것이다:

staring the pool map
got ^C while pool mapping, terminating the pool
pool is terminated
joining pool processes
join complete
the end

일반적으로 이 간단한 구조에 대한 작품 Ctrl-C 에게 구성되어 있습니다.

def signal_handle(_signal, frame):
    print "Stopping the Jobs."

signal.signal(signal.SIGINT, signal_handle)

로에서 언급 몇 가지 유사한 게시물:

캡처 keyboardinterrupt 에서는 파이썬 없이도를 제외하고

그것은 보인다 거기에는 두 가지 문제들에게 예외는 동안 다중니다.첫(주목에 의해 글렌)을 사용해야하는 map_async 시간 초과신 map 을 얻기 위해서 즉각적인 응답을(즉,완료하지 않는 처리 전체 목록).두 번째는(주목에 의해 안드레이)이는 최적화를 하는 c 컴파일러를 잡을 하지 않는 예외 없는 상속에서 Exception (예를 들어, SystemExit).그래서 여기 나의 솔루션을 거래하는 이들 모두와 함께:

import sys
import functools
import traceback
import multiprocessing

def _poolFunctionWrapper(function, arg):
    """Run function under the pool

    Wrapper around function to catch exceptions that don't inherit from
    Exception (which aren't caught by multiprocessing, so that you end
    up hitting the timeout).
    """
    try:
        return function(arg)
    except:
        cls, exc, tb = sys.exc_info()
        if issubclass(cls, Exception):
            raise # No worries
        # Need to wrap the exception with something multiprocessing will recognise
        import traceback
        print "Unhandled exception %s (%s):\n%s" % (cls.__name__, exc, traceback.format_exc())
        raise Exception("Unhandled exception: %s (%s)" % (cls.__name__, exc))

def _runPool(pool, timeout, function, iterable):
    """Run the pool

    Wrapper around pool.map_async, to handle timeout.  This is required so as to
    trigger an immediate interrupt on the KeyboardInterrupt (Ctrl-C); see
    http://stackoverflow.com/questions/1408356/keyboard-interrupts-with-pythons-multiprocessing-pool

    Further wraps the function in _poolFunctionWrapper to catch exceptions
    that don't inherit from Exception.
    """
    return pool.map_async(functools.partial(_poolFunctionWrapper, function), iterable).get(timeout)

def myMap(function, iterable, numProcesses=1, timeout=9999):
    """Run the function on the iterable, optionally with multiprocessing"""
    if numProcesses > 1:
        pool = multiprocessing.Pool(processes=numProcesses, maxtasksperchild=1)
        mapFunc = functools.partial(_runPool, pool, timeout)
    else:
        pool = None
        mapFunc = map
    results = mapFunc(function, iterable)
    if pool is not None:
        pool.close()
        pool.join()
    return results

는 투표에 대답하지 않을 해결핵 문제는 하지만 비슷한 부작용이 없습니다.

Jesse Noller,저자의 최적화를 하는 c 컴파일러,라이브러리를 설명하는 방법이 올바르게 처리 CTRL+C 를 사용하는 경우 multiprocessing.Pool 에서 옛 블로그 게시물.

import signal
from multiprocessing import Pool


def initializer():
    """Ignore CTRL+C in the worker process."""
    signal.signal(signal.SIGINT, signal.SIG_IGN)


pool = Pool(initializer=initializer)

try:
    pool.map(perform_download, dowloads)
except KeyboardInterrupt:
    pool.terminate()
    pool.join()

내가 발견한 최고의 솔루션을 사용하지원합니다..수영장기능지만 오히려 자신의 롤 수영장 기능이 있습니다.내가 제공한 예를 보여주는 오류를 apply_async 로 보여주는 예제를 방지하는 방법을 사용하여 수영장 기능을 모두 합니다.

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

나는 초보자에서 Python.내가 찾고 있었던 모든 곳에서 대답하고 우연히 이와 몇 가지 다른 블로그 및 유튜브 동영상입니다.을 붙여 복사자의 위 코드와 재현에 내 python2.7.13windows7 64 비트입니다.그것에 가까이 무엇이 내가 달성했다.

나는 내 자식 프로세스를 무시하 ControlC 고 부모 프로세스가 종료됩니다.처럼 보이 우회하는 자식 프로세스가 이러한 문제를 방지한다.

#!/usr/bin/python

from multiprocessing import Pool
from time import sleep
from sys import exit


def slowly_square(i):
    try:
        print "<slowly_square> Sleeping and later running a square calculation..."
        sleep(1)
        return i * i
    except KeyboardInterrupt:
        print "<child processor> Don't care if you say CtrlC"
        pass


def go():
    pool = Pool(8)

    try:
        results = pool.map(slowly_square, range(40))
    except KeyboardInterrupt:
        pool.terminate()
        pool.close()
        print "You cancelled the program!"
        exit(1)
    print "Finally, here are the results", results


if __name__ == '__main__':
    go()

부분에서 시작 pool.terminate() 결코 실행하는 것 같습니다.

사용할 수 있습니다 apply_async 방법의 수영장 개체에 다음과 같다:

import multiprocessing
import time
from datetime import datetime


def test_func(x):
    time.sleep(2)
    return x**2


def apply_multiprocessing(input_list, input_function):
    pool_size = 5
    pool = multiprocessing.Pool(processes=pool_size, maxtasksperchild=10)

    try:
        jobs = {}
        for value in input_list:
            jobs[value] = pool.apply_async(input_function, [value])

        results = {}
        for value, result in jobs.items():
            try:
                results[value] = result.get()
            except KeyboardInterrupt:
                print "Interrupted by user"
                pool.terminate()
                break
            except Exception as e:
                results[value] = e
        return results
    except Exception:
        raise
    finally:
        pool.close()
        pool.join()


if __name__ == "__main__":
    iterations = range(100)
    t0 = datetime.now()
    results1 = apply_multiprocessing(iterations, test_func)
    t1 = datetime.now()
    print results1
    print "Multi: {}".format(t1 - t0)

    t2 = datetime.now()
    results2 = {i: test_func(i) for i in iterations}
    t3 = datetime.now()
    print results2
    print "Non-multi: {}".format(t3 - t2)

출력:

100
Multiprocessing run time: 0:00:41.131000
100
Non-multiprocessing run time: 0:03:20.688000

는 이 방법의 장점은 결과를 처리하기 전에 중단이 될 것입니다에서 반환된 결과를 사전

>>> apply_multiprocessing(range(100), test_func)
Interrupted by user
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

이상하게도 그것은 다음과 같이 있을 처리 KeyboardInterrupt 에서뿐만 아니라 아이들.가 이 일을 서면으로...변경하십시오 slowly_square 하기:

def slowly_square(i):
    try:
        sleep(1)
        return i * i
    except KeyboardInterrupt:
        print 'You EVIL bastard!'
        return 0

작동할 것으로 예상된다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top