0

私はこのトピックに関する他のところで多くの質問を読んだことがありますが、それは機能しません。おそらくそれは私がWindowsを使っているからだと私は知らない。ファイルをconcurrent.futuresまたはmultiprocessingでダウンロードする - Ctrl-Cで停止するには?

私がしようとしているのは、(URLがCSVファイルから読み込まれた)たくさんのファイルを並行してダウンロードすることです。私はmultiprocessingconcurrent.futuresを使ってこれを成功させようとしました。

主な問題は、Ctrl-Cでプログラムを停止できないことです。実行し続けるだけです。これは、毎回手動で各プロセスを強制終了する必要があるため、スレッドの代わりにプロセスの場合は特に悪いです(私はmultiprocessingを使用しました)。

は、ここに私の現在のコードです:私はここに2つの異なる方法ではCtrl-Cをキャッチしようとしている

import concurrent.futures 
import signal 
import sys 
import urllib.request 

class Download(object): 
    def __init__(self, url, filename): 
    self.url = url 
    self.filename = filename 

def perform_download(download): 
    print('Downloading {} to {}'.format(download.url, download.filename)) 
    return urllib.request.urlretrieve(download.url, filename=download.filename) 

def main(argv): 
    args = parse_args(argv) 
    queue = [] 
    with open(args.results_file, 'r', encoding='utf8') as results_file: 
    # Irrelevant CSV parsing... 
    queue.append(Download(url, filename)) 

    def handle_interrupt(): 
    print('CAUGHT SIGINT!!!!!!!!!!!!!!!!!!!11111111') 
    sys.exit(1) 

    signal.signal(signal.SIGINT, handle_interrupt) 

    with concurrent.futures.ThreadPoolExecutor(max_workers=args.num_jobs) as executor: 
    futures = {executor.submit(perform_download, d): d for d in queue} 
    try: 
     concurrent.futures.wait(futures) 
    except KeyboardInterrupt: 
     print('Interrupted') 
     sys.exit(1) 

それらのどれも機能しません。後者のもの(except KeyboardInterrupt)は実際に実行されますが、プロセスはsys.exitを呼び出した後に終了しません。この前

は、私はこのようなmultiprocessingモジュールを使用:

try:  
    pool = multiprocessing.Pool(processes=args.num_jobs) 
    pool.map_async(perform_download, queue).get(1000000) 
    except Exception as e: 
    pool.close() 
    pool.terminate() 
    sys.exit(0) 

ですから、ターミナルでCtrl-Cを押した後、すべてのワーカースレッドやプロセスを終了する機能を追加するための適切な方法は何ですか?

システム情報:

  • Pythonのバージョン:3.6.1 32ビット
  • OS:Windowsの10
+0

は、少なくともマルチプロセッシングモジュールのために、それは既知のバグです: http://bugs.python.org/issue8296 も https://stackoverflow.com/questions/1408356/keyboard-interruptsを見ます-with-pythons-multiprocessing-pool –

+0

これは私のために働いています。https://stackoverflow.com/a/31795242/4385319 – technusm1

答えて

0

あなたはシグナルハンドラでSIGINT信号をキャッチし、それを再ルーティングしていますSystemExit例外としてこれにより、KeyboardInterrupt例外がメインループに到達することがなくなります。また、SystemExitがメインスレッドで発生していない場合は、発生した子スレッドを殺すだけです。

multiprocessingライブラリの著者Jesse Nollerは、blog postCTRL+Cを処理する方法を説明しています。

import signal 
from multiprocessing import Pool 


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


pool = Pool(initializer=initializer) 

try: 
    pool.map(perform_download, dowloads) 
except KeyboardInterrupt: 
    pool.terminate() 
    pool.join() 
関連する問題