วิธีแยก time.sleep() ใน python concurrent.futures

ฉันกำลังเล่นกับ concurrent.futures

ปัจจุบันการโทรในอนาคตของฉัน time.sleep(secs)

ดูเหมือนว่า Future.cancel()ทำได้น้อยกว่าที่คิด

หากอนาคตกำลังดำเนินอยู่ time.sleep() จะไม่ถูกยกเลิก

เช่นเดียวกับพารามิเตอร์การหมดเวลาสำหรับ wait(). มันไม่ได้ยกเลิก time.sleep() ของฉัน

จะยกเลิก time.sleep() ที่ถูกดำเนินการใน concurrent.futures ได้อย่างไร

สำหรับการทดสอบ ฉันใช้ ThreadPoolExecutor


person guettli    schedule 19.07.2016    source แหล่งที่มา
comment
คำตอบสั้น ๆ - ไม่มีทาง และการใช้ sleep ในคนงานส่วนใหญ่อาจหมายถึงปัญหากับการออกแบบ คำตอบยาว ๆ - คุณสามารถใช้ sleep แบบกำหนดเองได้โดยมีความเป็นไปได้ที่จะทำลายพวกมันได้เสมอ อย่างไรก็ตาม มันก็ไม่ใช่ทั้ง pythonic หรือถูกต้อง เป็นทางเลือกหนึ่งที่คุณสามารถตรวจสอบการใช้งานล็อคได้   -  person Reishin    schedule 01.08.2016


คำตอบ (3)


หากคุณส่งฟังก์ชันไปที่ ThreadPoolExecutor ตัวดำเนินการจะเรียกใช้ฟังก์ชันในเธรดและเก็บค่าที่ส่งคืนไว้ในอ็อบเจ็กต์ Future เนื่องจากจำนวนเธรดที่เกิดขึ้นพร้อมกันนั้นมีจำกัด คุณจึงมีตัวเลือกในการ ยกเลิก การดำเนินการ รอดำเนินการ ในอนาคต แต่เมื่อการควบคุมในเธรดของผู้ปฏิบัติงานได้ถูกส่งผ่านไปยังผู้เรียกแล้ว ไม่มีทางหยุดการดำเนินการได้

พิจารณารหัสนี้:

import concurrent.futures as f
import time

T = f.ThreadPoolExecutor(1) # Run at most one function concurrently
def block5():
    time.sleep(5)
    return 1
q = T.submit(block5)
m = T.submit(block5)

print q.cancel()  # Will fail, because q is already running
print m.cancel()  # Will work, because q is blocking the only thread, so m is still queued

โดยทั่วไป เมื่อใดก็ตามที่คุณต้องการมีบางสิ่งที่สามารถยกเลิกได้ คุณเองก็ต้องรับผิดชอบในการตรวจสอบให้แน่ใจว่าเป็นเช่นนั้น

มีตัวเลือกบางอย่างที่มีจำหน่ายทั่วไป เช่น ลองใช้ asyncio พวกเขายัง มี ตัวอย่างการใช้โหมดสลีป แนวคิดนี้หลีกเลี่ยงปัญหาโดยเมื่อใดก็ตามที่มีการเรียกใช้การดำเนินการบล็อกที่อาจเกิดขึ้น แทนที่จะส่งคืนการควบคุมไปยังลูปควบคุมที่ทำงานในบริบทภายนอกสุด พร้อมด้วยหมายเหตุว่าการดำเนินการควรดำเนินต่อไปเมื่อใดก็ตามที่ผลลัพธ์พร้อมใช้งาน - หรือใน กรณีของคุณหลังจากผ่านไป n วินาที

person Phillip    schedule 25.07.2016
comment
โอ้สนุกจริงๆ :-) ฉันเปลี่ยนจากการประมวลผลหลายตัวเป็น concurrent.futures (ด้วยเหตุผลอื่น) ตอนนี้ฉันกำลังคิดที่จะเปลี่ยนจาก concurrent.futures เป็น asyncio ... :-) อย่างไรก็ตาม ฟิลลิป ขอบคุณสำหรับคำตอบของคุณ! - person guettli; 25.07.2016
comment
ยินดีต้อนรับ ???? อย่างไรก็ตาม ด้วย multiprocessing การขัดจังหวะ sleep ก็เป็นไปได้ เพราะแน่นอนว่าคุณสามารถ kill กระบวนการอื่นๆ ได้ - person Phillip; 25.07.2016
comment
@ ฉันคิดว่าฉันสามารถใช้ kill ใน concurrent.futures ได้เช่นกัน ฉันแค่ต้องเปลี่ยนจาก ThreadPoolExecutor เป็น ProcessPoolExecutor หรือนี่ผิด? - person guettli; 25.07.2016
comment
ตามทฤษฎีแล้ว ใช่ แต่ (a) คุณลักษณะ _processes ไม่ได้รับการบันทึกไว้และอาจมีการเปลี่ยนแปลง และ (b) หลังจากที่คุณตรวจพบว่าอนาคตของคุณกำลังทำงานอยู่และยังไม่เสร็จสิ้น คุณจะมีการแข่งขันระหว่าง การจบอนาคตและคุณฆ่ามัน ถ้าคุณแพ้ คุณจะฆ่างานอื่น (ที่ไม่เกี่ยวข้อง) แทนที่จะเป็นงานที่คุณตั้งใจไว้ - person Phillip; 25.07.2016
comment
AFAIK linux จะเพิ่ม PID สำหรับแต่ละกระบวนการใหม่ โดยวนซ้ำหากถึงขีดจำกัดบน ไม่น่าเป็นไปได้มากที่สิ่งนี้จะเกิดขึ้น แต่คุณพูดถูก: มันเป็นสภาพการแข่งขัน - person guettli; 25.07.2016
comment
มันเป็น พูล ของกระบวนการ หลามไม่ได้สร้างกระบวนการใหม่สำหรับทุกๆ งาน! - person Phillip; 25.07.2016
comment
การประมวลผลหลายตัวและ concurrent.futures แตกต่างกันในด้านนี้หรือไม่ AFAIK ทั้งคู่ใช้พูลกระบวนการ - person guettli; 25.07.2016
comment
ด้วยการประมวลผลหลายตัว คุณสามารถใช้คลาส Process ได้โดยตรงเพื่อแทรกการป้องกันของคุณเอง อีกครั้ง คุณสามารถคลาสย่อย ProcessPoolExecutor และเพิ่มความสามารถในการยุติอย่างปลอดภัยได้ - person Phillip; 26.07.2016
comment
ฉันไม่พบเอกสารเกี่ยวกับการใส่การป้องกันในเอกสารอย่างเป็นทางการ กรณีที่ 1: ฉันตาบอด กรณีที่ 2: เอกสารอย่างเป็นทางการไม่ครอบคลุมเรื่องนี้ หากเป็นกรณีที่ 2: คุณคิดว่าควรจัดทำเอกสารนี้หรือไม่ ฉันไม่เชื่อบล็อกโพสต์หรือแหล่งข้อมูลของบุคคลที่สามอื่นๆ ในระยะยาวจะล้าสมัยและไม่ได้รับการดูแลอย่างดี - person guettli; 26.07.2016
comment
กรณีที่ 2 และฉันไม่คิดว่าสิ่งนี้ควรได้รับการบันทึกไว้เพราะนี่คือแนวทางปฏิบัติที่ดีที่สุด ไม่ และมีประโยชน์เฉพาะในกรณีมุมเท่านั้น กล่าวคือ หากคุณมีงานที่ต้องใช้เวลานานจำนวนมาก (ไม่เช่นนั้นก็ไม่มี จำเป็นต้องยกเลิกสิ่งใด ๆ เพียงแค่ปล่อยให้มันดำเนินต่อไปและเพิกเฉยต่อผลลัพธ์) ซึ่งคุณ อย่างมาก แทบจะไม่จำเป็นต้องยกเลิก (ไม่เช่นนั้น killing กระบวนการในแต่ละครั้งจะมากเกินไป และคุณควรออกแบบงานของคุณให้สามารถยกเลิกได้จริงๆ) - person Phillip; 26.07.2016
comment
@ ฟิลลิปฉันเข้าใจว่า asyncio การเขียนโปรแกรมเชิงฟังก์ชันได้รับความนิยม แต่การหมดเวลาการนอนหลับไม่มีอะไรที่จะ asyncio ฉันจะพูดด้วยว่าถ้าเขาใช้ sleep ใน ThreadedPool ดูเหมือนว่าเขาจะมีปัญหากับการออกแบบแอปพลิเคชันและแม้แต่ asyncio ก็จะไม่ปลอดภัยสำหรับเขา - person Reishin; 01.08.2016
comment
@Reishin โปรดทราบว่าตัวอย่าง asyncio ใช้ asyncio.sleep ไม่ใช่ time.sleep time.sleep สามารถขัดจังหวะได้โดยการส่งสัญญาณไปยังกระบวนการสลีปเท่านั้น โดยไม่คำนึงถึงอินเทอร์เฟซของ Python ประเด็นของฉันคือถ้าคุณต้องการนอนหลับโดยไม่ขัดจังหวะ คุณไม่ควรใช้ nanosleep(2) เลย แต่ควรใช้ select(2) บน eventfd(2) โดยใช้การหมดเวลาแทน asyncio เป็นหนึ่งใน wrapper ที่เป็นไปได้สำหรับ API นี้ (และที่คล้ายกัน) - person Phillip; 01.08.2016
comment
@Phillip asyncio.sleep เคยให้โอกาสสตรีมอื่นได้รับการประมวลผลในขณะที่ผู้โทรจะรอ และไม่มีการรับประกันว่าจะใช้เวลาใน 1 หรือ 2 วินาที (เนื่องจากลักษณะของ asyncio) การใช้งานอื่น ๆ เช่น ขึ้นอยู่กับแพลตฟอร์ม eventfd r และนี่คือคำถามง่าย ๆ - วิธีแบ่ง time.sleep ไม่ใช่วิธีแก้ปัญหาเพื่อให้สิ่งนี้เป็นไปได้ - person Reishin; 01.08.2016
comment
@Reishin ทั้งหมด ฟังก์ชัน asyncio ถูกใช้เพื่อให้ส่วนอื่นๆ ของโปรแกรมมีโอกาสได้รับการประมวลผล นั่นคือประเด็นทั้งหมดและเหตุผลว่าทำไมโมดูลจึงสามารถใช้เป็นช่องทางสำหรับผู้เขียนในการเขียนอัลกอริธึมที่ขัดจังหวะได้ หากคุณใช้อะซิงโครนัสอย่างถูกต้อง asyncio.sleep ไม่รับประกันว่าคุณเข้าสู่โหมดสลีปตามระยะเวลาที่กำหนด (ขึ้นอยู่กับความละเอียดของลูปเหตุการณ์) ฉันไม่เห็นด้วยกับลักษณะของคำถาม time.sleep ถูกใช้โดยผู้เขียนเป็นตัวอย่าง; สิ่งที่เขาขอคืองาน (ที่กำลังดำเนินการอยู่) ซึ่งผลลัพธ์ถูกห่อหุ้มด้วย Future สามารถยกเลิกได้อย่างไร - person Phillip; 02.08.2016

ฉันไม่ค่อยมีความรู้เกี่ยวกับ concurrent.futures มากนัก แต่คุณสามารถใช้ตรรกะนี้เพื่อแบ่งเวลาได้ ใช้การวนซ้ำแทน sleep.time() หรือ wait()

for i in range(sec):
    sleep(1)

ขัดจังหวะหรือหยุดสามารถใช้เพื่อออกจากวงได้

person ketan khandagale    schedule 28.07.2016
comment
ใช่มันใช้งานได้ รู้สึกเหมือนกับผู้ชายจากฟินแลนด์ที่ต้องการอ่านอีเมลผ่านการเชื่อมต่อผ่านสายโทรศัพท์... อืม ฉันต้องการ event-loop .... ฉันต้องการตัวกำหนดเวลา .... และสุดท้ายมันก็เป็นระบบปฏิบัติการ - person guettli; 28.07.2016

ตามที่เขียนไว้ในลิงก์ คุณสามารถ ใช้คำสั่ง with เพื่อให้แน่ใจว่าเธรดได้รับการทำความสะอาดทันที ดังตัวอย่างด้านล่าง:

import concurrent.futures
import urllib.request

URLS = ['http://www.foxnews.com/',
        'http://www.cnn.com/',
        'http://europe.wsj.com/',
        'http://www.bbc.co.uk/',
        'http://some-made-up-domain.com/']

# Retrieve a single page and report the URL and contents
def load_url(url, timeout):
    with urllib.request.urlopen(url, timeout=timeout) as conn:
        return conn.read()

# We can use a with statement to ensure threads are cleaned up promptly
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
    # Start the load operations and mark each future with its URL
    future_to_url = {executor.submit(load_url, url, 60): url for url in URLS}
    for future in concurrent.futures.as_completed(future_to_url):
        url = future_to_url[future]
        try:
            data = future.result()
        except Exception as exc:
            print('%r generated an exception: %s' % (url, exc))
        else:
            print('%r page is %d bytes' % (url, len(data)))
person iraf    schedule 07.01.2021