หมดเวลาสำหรับการร้องขอของ python รับคำตอบทั้งหมด


169

ฉันกำลังรวบรวมสถิติในรายการเว็บไซต์และฉันใช้คำขอเพื่อความเรียบง่าย นี่คือรหัสของฉัน:

data=[]
websites=['http://google.com', 'http://bbc.co.uk']
for w in websites:
    r= requests.get(w, verify=False)
    data.append( (r.url, len(r.content), r.elapsed.total_seconds(), str([(l.status_code, l.url) for l in r.history]), str(r.headers.items()), str(r.cookies.items())) )

ตอนนี้ฉันต้องการrequests.getหมดเวลาหลังจาก 10 วินาทีดังนั้นการวนซ้ำไม่ติด

คำถามนี้ได้รับความสนใจมาก่อนเช่นกัน แต่ไม่มีคำตอบใดที่สะอาด ฉันจะวางรางวัลนี้เพื่อรับคำตอบที่ดี

ฉันได้ยินมาว่าอาจไม่ได้ใช้การร้องขอเป็นความคิดที่ดี แต่ถ้าอย่างนั้นฉันจะได้รับสิ่งที่ดีได้อย่างไร (สิ่งที่อยู่ใน tuple)


1
คุณต้องการคำตอบประเภทใด (หรืออีกนัยหนึ่งทำไมคำตอบปัจจุบันถึงไม่เพียงพอสำหรับคุณ)
yuvi

เราอยู่ในช่วงผ่อนผันของการรับรางวัล ได้เวลาเลือกคำตอบแล้วหรือยัง?
totokaka

ฉันยังคงตัดสินใจเลือกระหว่างโซลูชันของเหตุการณ์และสัญญาณ ฉันจะให้รางวัลคำถามในคืนนี้
Kiarash


คำตอบ:


137

แล้วการใช้ eventlet ล่ะ? หากคุณต้องการหมดเวลาคำขอหลังจาก 10 วินาทีแม้ว่าจะได้รับข้อมูลตัวอย่างนี้จะทำงานให้คุณ:

import requests
import eventlet
eventlet.monkey_patch()

with eventlet.Timeout(10):
    requests.get("http://ipv4.download.thinkbroadband.com/1GB.zip", verify=False)

115
แน่นอนว่ามันซับซ้อนโดยไม่จำเป็น
holdenweb

7
ขอบคุณ. ตอนนี้ฉันเข้าใจถึงความเหนือกว่าด้านเทคนิคของโซลูชันของคุณ (ซึ่งคุณระบุไว้ค่อนข้างชัดเจนในตอนต้นของคำตอบของคุณ) และยกระดับขึ้น ปัญหาเกี่ยวกับโมดูลของบุคคลที่สามไม่ได้นำเข้าพวกเขา แต่ให้แน่ใจว่าพวกเขาจะมีการนำเข้าดังนั้นฉันตั้งค่าตัวเองสำหรับการใช้ห้องสมุดมาตรฐานที่เป็นไปได้
holdenweb

9
ถูกeventlet.monkey_patch()ต้อง?
ผู้ใช้

3
ใช่socketโมดูลจะต้องมีการติดตั้งลิงดังนั้นอย่างน้อยคุณจะต้องeventlet.monkey_patch(socket=True)
Alvaro

53
ในปี 2018คำตอบนี้ล้าสมัยแล้ว ใช้requests.get('https://github.com', timeout=5)
CONVid19

313

ตั้งค่า พารามิเตอร์การหมดเวลา :

r = requests.get(w, verify=False, timeout=10) # 10 seconds

ตราบใดที่คุณไม่ได้ตั้งค่าstream=Trueตามคำร้องขอสิ่งนี้จะทำให้การเรียกใช้requests.get()การหมดเวลาหากการเชื่อมต่อใช้เวลานานกว่าสิบวินาทีหรือหากเซิร์ฟเวอร์ไม่ส่งข้อมูลเป็นเวลานานกว่าสิบวินาที


31
นั่นไม่ใช่สำหรับการตอบสนองทั้งหมด requests.readthedocs.org/en/latest/user/quickstart/#timeouts
Kiarash

1
ใช่มันเป็นในบางสถานการณ์ หนึ่งในสถานการณ์เหล่านั้นเกิดขึ้นเป็นของคุณ =) ฉันขอเชิญคุณดูรหัสหากคุณไม่มั่นใจ
Lukasa

สถานการณ์อะไร
Kiarash

1
ฉันเพิ่งตรวจสอบสิ่งนี้และไม่เคยหยุด: r = คำร้องขอรับ (' ipv4.download.thinkbroadband.com/1GB.zip ' หมดเวลา = 20)
Kiarash

5
อาขอโทษฉันเข้าใจผิดว่าคุณหมายถึงอะไรเมื่อคุณพูดว่า 'คำตอบทั้งหมด' ใช่คุณพูดถูก: ไม่ใช่ขีด จำกัด สูงสุดของจำนวนเวลาทั้งหมดที่จะรอ
Lukasa

85

อัปเดต: https://requests.readthedocs.io/en/master/user/advanced/#timeouts

ในเวอร์ชันใหม่ของrequests:

หากคุณระบุค่าเดียวสำหรับการหมดเวลาเช่นนี้:

r = requests.get('https://github.com', timeout=5)

ค่าการหมดเวลาจะถูกนำไปใช้กับทั้งconnectและreadหมดเวลา ระบุ tuple หากคุณต้องการตั้งค่าแยก:

r = requests.get('https://github.com', timeout=(3.05, 27))

หากเซิร์ฟเวอร์ระยะไกลช้ามากคุณสามารถบอกให้คำขอรอตลอดการตอบกลับโดยผ่านไม่มีค่าการหมดเวลาแล้วเรียกกาแฟหนึ่งถ้วย

r = requests.get('https://github.com', timeout=None)

คำตอบเก่า (อาจล้าสมัย) ของฉัน (ซึ่งโพสต์เมื่อนานมาแล้ว):

มีวิธีอื่นในการเอาชนะปัญหานี้:

1. ใช้TimeoutSauceคลาสภายใน

จาก: https://github.com/kennethreitz/requests/issues/1928#issuecomment-35811896

import requests from requests.adapters import TimeoutSauce

class MyTimeout(TimeoutSauce):
    def __init__(self, *args, **kwargs):
        connect = kwargs.get('connect', 5)
        read = kwargs.get('read', connect)
        super(MyTimeout, self).__init__(connect=connect, read=read)

requests.adapters.TimeoutSauce = MyTimeout

รหัสนี้ควรทำให้เราตั้งค่าการหมดเวลาการอ่านเท่ากับการหมดเวลาเชื่อมต่อซึ่งเป็นค่าการหมดเวลาที่คุณส่งผ่านการเรียก Session.get () (โปรดทราบว่าฉันไม่ได้ทดสอบโค้ดนี้จริง ๆ ดังนั้นจึงอาจต้องมีการดีบักอย่างรวดเร็วฉันเพิ่งเขียนมันลงในหน้าต่าง GitHub โดยตรง)

2. ใช้คำขอแยกจาก kevinburke: https://github.com/kevinburke/requests/tree/connect-timeout

จากเอกสารของ: https://github.com/kevinburke/requests/blob/connect-timeout/docs/user/advanced.rst

หากคุณระบุค่าเดียวสำหรับการหมดเวลาเช่นนี้:

r = requests.get('https://github.com', timeout=5)

ค่าการหมดเวลาจะถูกนำไปใช้กับทั้งการเชื่อมต่อและการหมดเวลาการอ่าน ระบุ tuple หากคุณต้องการตั้งค่าแยก:

r = requests.get('https://github.com', timeout=(3.05, 27))

kevinburke ขอให้รวมเข้ากับโครงการคำขอหลัก แต่ยังไม่ได้รับการยอมรับ


ตัวเลือก 1 ไม่ทำงาน ถ้าคุณอ่านเธรดต่อไปคนอื่น ๆ ก็พูดว่า "มันไม่ได้ผลกับการใช้งานของคุณฉันเกรงว่าฟังก์ชั่นการหมดเวลาการอ่านจะอยู่ที่ขอบเขตของการเรียกซ็อกเก็ต recv () ซ็อกเก็ตแต่ละตัว หยุดส่งข้อมูลมากกว่าการหมดเวลาอ่านที่เราจะยกเลิก "
Kiarash

มีอีกวิธีที่ดีในเธรดที่ใช้สัญญาณซึ่งไม่ได้ผลสำหรับฉันเช่นกันเพราะฉันใช้ Windows และ signal.alarm เป็นลินุกซ์เท่านั้น
Kiarash

@ Kiarash ฉันยังไม่ได้ทดสอบ แต่ที่ผมเข้าใจเมื่อ Lukasa this won't work for you use-caseกล่าวว่า เขาหมายถึงมันไม่ทำงานกับสตรีม mp3 ที่คนอื่นต้องการ
Hieu

1
@Hieu - นี่ถูกรวมในคำขอดึงอีกครั้ง - github.com/kennethreitz/requests/pull/ …
yprez

หมดเวลา = ไม่มีไม่บล็อกการโทร
crazydan

49

timeout = int(seconds)

เนื่องจาก requests >= 2.4.0คุณสามารถใช้timeoutอาร์กิวเมนต์เช่น:

requests.get('https://duckduckgo.com/', timeout=10)

บันทึก:

timeoutไม่ จำกัด เวลาในการดาวน์โหลดการตอบสนองทั้งหมด ค่อนข้างexceptionจะเพิ่มขึ้นถ้าเซิร์ฟเวอร์ไม่ได้ออกการตอบสนองสำหรับการหมดเวลาวินาที หากไม่มีการระบุการหมดเวลาอย่างชัดเจนคำขอจะไม่หมดเวลา


คำขอเวอร์ชันใดที่มีพารามิเตอร์การหมดเวลาใหม่
Rusty

1
ดูเหมือนว่าจะเป็นรุ่น 2.4.0: รองรับการหมดเวลาเชื่อมต่อ! ขณะนี้การหมดเวลายอมรับ tuple (เชื่อมต่ออ่าน) ซึ่งใช้สำหรับตั้งค่าการเชื่อมต่อและอ่านหมดเวลาแต่ละรายการ pypi.org/project/requests/2.4.0
CONvid19

23

หมดเวลาในการสร้างคุณสามารถใช้สัญญาณ

วิธีที่ดีที่สุดในการแก้ไขกรณีนี้น่าจะเป็น

  1. ตั้งค่าข้อยกเว้นเป็นตัวจัดการสำหรับสัญญาณเตือน
  2. โทรสัญญาณเตือนด้วยความล่าช้าสิบวินาที
  3. เรียกใช้ฟังก์ชันภายในtry-except-finallyบล็อก
  4. ถึงยกเว้นบล็อกถ้าฟังก์ชั่นหมดเวลา
  5. ในที่สุดก็บล็อกคุณยกเลิกการเตือนภัยดังนั้นจึงไม่มีการประกาศในภายหลัง

นี่คือตัวอย่างรหัส:

import signal
from time import sleep

class TimeoutException(Exception):
    """ Simple Exception to be called on timeouts. """
    pass

def _timeout(signum, frame):
    """ Raise an TimeoutException.

    This is intended for use as a signal handler.
    The signum and frame arguments passed to this are ignored.

    """
    # Raise TimeoutException with system default timeout message
    raise TimeoutException()

# Set the handler for the SIGALRM signal:
signal.signal(signal.SIGALRM, _timeout)
# Send the SIGALRM signal in 10 seconds:
signal.alarm(10)

try:    
    # Do our code:
    print('This will take 11 seconds...')
    sleep(11)
    print('done!')
except TimeoutException:
    print('It timed out!')
finally:
    # Abort the sending of the SIGALRM signal:
    signal.alarm(0)

มีข้อแม้บางประการดังนี้:

  1. มันไม่ได้เป็นเธรดที่ปลอดภัยสัญญาณจะถูกส่งไปยังเธรดหลักเสมอดังนั้นคุณจึงไม่สามารถใส่สิ่งนี้ในเธรดอื่นได้
  2. มีความล่าช้าเล็กน้อยหลังจากกำหนดเวลาของสัญญาณและการดำเนินการของรหัสจริง ซึ่งหมายความว่าตัวอย่างจะหมดเวลาแม้ว่าจะนอนเพียงสิบวินาทีเท่านั้น

แต่ทั้งหมดนี้อยู่ในไลบรารี python มาตรฐาน! ยกเว้นการนำเข้าฟังก์ชั่นการนอนหลับมันเป็นเพียงการนำเข้าเดียว หากคุณกำลังจะใช้การหมดเวลาหลายสถานที่คุณสามารถใส่ TimeoutException, _timeout และการร้องเพลงในฟังก์ชั่นและเรียกสิ่งนั้นได้อย่างง่ายดาย หรือคุณสามารถสร้างมัณฑนากรและวางลงบนฟังก์ชั่นดูคำตอบที่ลิงก์ด้านล่าง

คุณสามารถตั้งค่านี้เป็น"ตัวจัดการบริบท"เพื่อให้คุณสามารถใช้กับwithคำสั่ง:

import signal
class Timeout():
    """ Timeout for use with the `with` statement. """

    class TimeoutException(Exception):
        """ Simple Exception to be called on timeouts. """
        pass

    def _timeout(signum, frame):
        """ Raise an TimeoutException.

        This is intended for use as a signal handler.
        The signum and frame arguments passed to this are ignored.

        """
        raise Timeout.TimeoutException()

    def __init__(self, timeout=10):
        self.timeout = timeout
        signal.signal(signal.SIGALRM, Timeout._timeout)

    def __enter__(self):
        signal.alarm(self.timeout)

    def __exit__(self, exc_type, exc_value, traceback):
        signal.alarm(0)
        return exc_type is Timeout.TimeoutException

# Demonstration:
from time import sleep

print('This is going to take maximum 10 seconds...')
with Timeout(10):
    sleep(15)
    print('No timeout?')
print('Done')

ข้อเสียอย่างหนึ่งที่เป็นไปได้กับวิธีการจัดการบริบทนี้คือคุณไม่สามารถทราบได้ว่ารหัสหมดเวลาจริงหรือไม่

แหล่งที่มาและการอ่านที่แนะนำ:


3
สัญญาณจะถูกส่งเฉพาะในหัวข้อหลักจึงdefnitelyจะไม่ทำงานในหัวข้ออื่น ๆ ที่ไม่อาจ
Dima Tisnek

1
หมดเวลา-มัณฑนากรแพคเกจให้มัณฑนากรหมดเวลาที่ใช้สัญญาณ (หรือเลือก multiprocessing)
Christian Long

13

ลองคำขอนี้ด้วยการจัดการหมดเวลาและข้อผิดพลาด:

import requests
try: 
    url = "http://google.com"
    r = requests.get(url, timeout=10)
except requests.exceptions.Timeout as e: 
    print e

5

ตั้งค่าและการใช้งานstream=True r.iter_content(1024)ใช่eventlet.Timeoutอย่างใดไม่ได้สำหรับฉัน

try:
    start = time()
    timeout = 5
    with get(config['source']['online'], stream=True, timeout=timeout) as r:
        r.raise_for_status()
        content = bytes()
        content_gen = r.iter_content(1024)
        while True:
            if time()-start > timeout:
                raise TimeoutError('Time out! ({} seconds)'.format(timeout))
            try:
                content += next(content_gen)
            except StopIteration:
                break
        data = content.decode().split('\n')
        if len(data) in [0, 1]:
            raise ValueError('Bad requests data')
except (exceptions.RequestException, ValueError, IndexError, KeyboardInterrupt,
        TimeoutError) as e:
    print(e)
    with open(config['source']['local']) as f:
        data = [line.strip() for line in f.readlines()]

การสนทนาอยู่ที่นี่https://redd.it/80kp1h


มันเป็นความอัปยศคำขอไม่สนับสนุน maxtime params วิธีนี้เป็นวิธีเดียวที่ทำงานร่วมกับ asyncio
14152

4

สิ่งนี้อาจ overkill แต่คิวงานกระจาย Celery มีการสนับสนุนที่ดีสำหรับการหมดเวลา

โดยเฉพาะอย่างยิ่งคุณสามารถกำหนดการ จำกัด เวลาซอฟท์ที่เพิ่งยกข้อยกเว้นในกระบวนการของคุณ (เพื่อให้คุณสามารถล้าง) และ / หรือการ จำกัด เวลาที่ยากที่จะยกเลิกงานเมื่อเกินเวลาที่ จำกัด

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


นี่อาจเป็นทางออกที่ดี ปัญหาการหมดเวลาทั้งหมดไม่เกี่ยวข้องโดยตรงกับpython-requestsแต่ไปที่httplib(ใช้โดยการร้องขอ Python 2.7) แพคเกจผ่านทุกสิ่งที่เกี่ยวข้องtimeoutโดยตรงกับ httplib ฉันคิดว่าไม่มีอะไรสามารถแก้ไขได้ตามคำร้องขอเนื่องจากกระบวนการสามารถอยู่เป็นเวลานานใน httplib
hynekcer

@ hynekcer ฉันคิดว่าคุณพูดถูก นี่คือเหตุผลที่การตรวจจับการหมดเวลานอกกระบวนการและบังคับใช้โดยกระบวนการฆ่าอย่างที่ Celery ทำนั้นเป็นวิธีการที่ดี
Chris Johnson

3

ฉันเชื่อว่าคุณสามารถใช้multiprocessingและไม่ได้ขึ้นอยู่กับแพ็คเกจของบุคคลที่สาม:

import multiprocessing
import requests

def call_with_timeout(func, args, kwargs, timeout):
    manager = multiprocessing.Manager()
    return_dict = manager.dict()

    # define a wrapper of `return_dict` to store the result.
    def function(return_dict):
        return_dict['value'] = func(*args, **kwargs)

    p = multiprocessing.Process(target=function, args=(return_dict,))
    p.start()

    # Force a max. `timeout` or wait for the process to finish
    p.join(timeout)

    # If thread is still active, it didn't finish: raise TimeoutError
    if p.is_alive():
        p.terminate()
        p.join()
        raise TimeoutError
    else:
        return return_dict['value']

call_with_timeout(requests.get, args=(url,), kwargs={'timeout': 10}, timeout=60)

การหมดเวลาที่ผ่านไปkwargsคือการหมดเวลาเพื่อรับการตอบกลับจากเซิร์ฟเวอร์อาร์กิวเมนต์timeoutคือการหมดเวลาเพื่อรับการตอบกลับที่สมบูรณ์


สิ่งนี้สามารถปรับปรุงได้ด้วยความพยายามทั่วไป / ยกเว้นในฟังก์ชั่นส่วนตัวที่จับข้อผิดพลาดทั้งหมดและทำให้พวกเขาใน return_dict ['ข้อผิดพลาด'] จากนั้นในตอนท้ายก่อนกลับมาตรวจสอบว่า 'ข้อผิดพลาด' ใน return_dict แล้วเพิ่มขึ้น มันทำให้การทดสอบง่ายขึ้นเช่นกัน
dialt0ne

2

หมดเวลา = (หมดเวลาการเชื่อมต่อ, หมดเวลาอ่านข้อมูล) หรือให้อาร์กิวเมนต์เดียว (หมดเวลา = 1)

import requests

try:
    req = requests.request('GET', 'https://www.google.com',timeout=(1,1))
    print(req)
except requests.ReadTimeout:
    print("READ TIME OUT")

1

รหัสนี้ใช้งานได้กับ socketError 11004 และ 10060 ......

# -*- encoding:UTF-8 -*-
__author__ = 'ACE'
import requests
from PyQt4.QtCore import *
from PyQt4.QtGui import *


class TimeOutModel(QThread):
    Existed = pyqtSignal(bool)
    TimeOut = pyqtSignal()

    def __init__(self, fun, timeout=500, parent=None):
        """
        @param fun: function or lambda
        @param timeout: ms
        """
        super(TimeOutModel, self).__init__(parent)
        self.fun = fun

        self.timeer = QTimer(self)
        self.timeer.setInterval(timeout)
        self.timeer.timeout.connect(self.time_timeout)
        self.Existed.connect(self.timeer.stop)
        self.timeer.start()

        self.setTerminationEnabled(True)

    def time_timeout(self):
        self.timeer.stop()
        self.TimeOut.emit()
        self.quit()
        self.terminate()

    def run(self):
        self.fun()


bb = lambda: requests.get("http://ipv4.download.thinkbroadband.com/1GB.zip")

a = QApplication([])

z = TimeOutModel(bb, 500)
print 'timeout'

a.exec_()

การเลื่อนตำแหน่งสำหรับความคิดสร้างสรรค์
JSmyth

1

แม้จะมีคำถามเกี่ยวกับคำขอ แต่ฉันพบว่าวิธีนี้ทำได้ง่ายด้วยpycurl CURLOPT_TIMEOUTหรือ CURLOPT_TIMEOUT_MS

ไม่จำเป็นต้องมีเธรดหรือการส่งสัญญาณ:

import pycurl
import StringIO

url = 'http://www.example.com/example.zip'
timeout_ms = 1000
raw = StringIO.StringIO()
c = pycurl.Curl()
c.setopt(pycurl.TIMEOUT_MS, timeout_ms)  # total timeout in milliseconds
c.setopt(pycurl.WRITEFUNCTION, raw.write)
c.setopt(pycurl.NOSIGNAL, 1)
c.setopt(pycurl.URL, url)
c.setopt(pycurl.HTTPGET, 1)
try:
    c.perform()
except pycurl.error:
    traceback.print_exc() # error generated on timeout
    pass # or just pass if you don't want to print the error

1

ในกรณีที่คุณใช้ตัวเลือกstream=Trueคุณสามารถทำได้:

r = requests.get(
    'http://url_to_large_file',
    timeout=1,  # relevant only for underlying socket
    stream=True)

with open('/tmp/out_file.txt'), 'wb') as f:
    start_time = time.time()
    for chunk in r.iter_content(chunk_size=1024):
        if chunk:  # filter out keep-alive new chunks
            f.write(chunk)
        if time.time() - start_time > 8:
            raise Exception('Request took longer than 8s')

วิธีการแก้ปัญหาไม่จำเป็นต้องมีสัญญาณหรือมัลติโพรเซสเซอร์


1

อีกโซลูชันหนึ่ง (ขอรับได้จากhttp://docs.python-requests.org/en/master/user/advanced/#streaming-uploads) )

ก่อนอัปโหลดคุณสามารถค้นหาขนาดเนื้อหา:

TOO_LONG = 10*1024*1024  # 10 Mb
big_url = "http://ipv4.download.thinkbroadband.com/1GB.zip"
r = requests.get(big_url, stream=True)
print (r.headers['content-length'])
# 1073741824  

if int(r.headers['content-length']) < TOO_LONG:
    # upload content:
    content = r.content

แต่ระวังผู้ส่งสามารถตั้งค่าที่ไม่ถูกต้องในฟิลด์การตอบสนอง 'ความยาวเนื้อหา'


ขอบคุณ ทางออกที่สะอาดและเรียบง่าย ได้ผลสำหรับฉัน
petezurich

0

หากเป็นเช่นนั้นให้สร้างเธรดสุนัขเฝ้าบ้านที่ทำให้สถานะคำขอภายในยุ่งเหยิงหลังจาก 10 วินาทีเช่น:

  • ปิดซ็อกเก็ตพื้นฐานและในอุดมคติ
  • ก่อให้เกิดข้อยกเว้นถ้าการร้องขอลองดำเนินการ

โปรดทราบว่าขึ้นอยู่กับไลบรารีระบบคุณอาจไม่สามารถกำหนดวันครบกำหนดในการแก้ไข DNS


0

ฉันลองวิธีแก้ปัญหามากมายในหน้านี้และยังคงเผชิญกับความไม่เสถียรแฮงค์สุ่มการเชื่อมต่อที่ไม่ดี

ตอนนี้ฉันใช้ Curl และฉันมีความสุขมากกับฟังก์ชั่น "เวลาสูงสุด" และเกี่ยวกับการแสดงทั่วโลกแม้จะมีการนำไปใช้ที่ไม่ดี:

content=commands.getoutput('curl -m6 -Ss "http://mywebsite.xyz"')

ที่นี่ฉันกำหนดพารามิเตอร์เวลาสูงสุด 6 วินาทีพร้อมทั้งเชื่อมต่อและถ่ายโอนเวลา

ฉันแน่ใจว่า Curl มีการรวมงูหลามที่ดีถ้าคุณชอบที่จะยึดติดกับ pythonic syntax :)


0

มีแพ็กเกจที่เรียกว่าtimeout-decoratorซึ่งคุณสามารถใช้ในการหมดเวลาฟังก์ชั่นของหลามได้

@timeout_decorator.timeout(5)
def mytest():
    print("Start")
    for i in range(1,10):
        time.sleep(1)
        print("{} seconds have passed".format(i))

มันใช้วิธีสัญญาณที่บางคำตอบแนะนำที่นี่ หรือคุณสามารถบอกให้ใช้มัลติโพรเซสเซอร์แทนสัญญาณ (เช่นหากคุณอยู่ในสภาพแวดล้อมแบบมัลติเธรด)


0

ฉันกำลังใช้คำขอ 2.2.1 และเหตุการณ์ไม่ทำงานสำหรับฉัน แต่ฉันสามารถใช้การหมดเวลาของ gevent แทนเนื่องจาก gevent ถูกใช้ในบริการของฉันสำหรับ gunicorn

import gevent
import gevent.monkey
gevent.monkey.patch_all(subprocess=True)
try:
    with gevent.Timeout(5):
        ret = requests.get(url)
        print ret.status_code, ret.content
except gevent.timeout.Timeout as e:
    print "timeout: {}".format(e.message)

โปรดทราบว่า gevent.timeout.Timeout ไม่ได้รับการจัดการโดยข้อยกเว้นทั่วไป ดังนั้นจะจับgevent.timeout.Timeout หรือส่งผ่านข้อยกเว้นที่แตกต่างกันอย่างชัดเจนเพื่อใช้เช่น: with gevent.Timeout(5, requests.exceptions.Timeout):แม้ว่าจะไม่มีการส่งข้อความเมื่อมีการยกข้อยกเว้นนี้


-1

ฉันคิดวิธีแก้ปัญหาโดยตรงที่น่าเกลียด แต่แก้ไขปัญหาจริง มันจะเป็นแบบนี้:

resp = requests.get(some_url, stream=True)
resp.raw._fp.fp._sock.settimeout(read_timeout)
# This will load the entire response even though stream is set
content = resp.content

คุณสามารถอ่านคำอธิบายทั้งหมดได้ที่นี่


3
1- เพราะคุณสามารถส่งผ่านtimeoutพารามิเตอร์requests.get()โดยไม่มีวิธีแก้ปัญหาที่น่าเกลียด 2- แม้ว่าทั้งสองจะไม่ จำกัด การหมดเวลารวมซึ่งแตกต่างeventlet.Timeout(10)
jfs
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.