через некоторое время Python запрашивает библиотеку с ошибочным файловым дескриптором - PullRequest
0 голосов
/ 19 сентября 2018

Я использую библиотеку запросов для очистки веб-сайта с интервалом.Я использую селен для входа и получения необходимых файлов cookie, а затем использую запросы для непосредственного обращения к API.Все работает хорошо в течение нескольких часов (30-50 запросов), а затем я неизменно получаю это исключение:

  File "attempt_enroll.py", line 104, in <module>
    resp = attemptEnroll(session)
  File "attempt_enroll.py", line 86, in attemptEnroll
    r = session.post(enroll_url, json=payload)
  File "/lib/python2.6/site-packages/requests/sessions.py", line 559, in post
    return self.request('POST', url, data=data, json=json, **kwargs)
  File "/lib/python2.6/site-packages/requests/sessions.py", line 512, in request
    resp = self.send(prep, **send_kwargs)
  File "/lib/python2.6/site-packages/requests/sessions.py", line 662, in send
    r.content
  File "/lib/python2.6/site-packages/requests/models.py", line 827, in content
    self._content = b''.join(self.iter_content(CONTENT_CHUNK_SIZE)) or b''
  File "/lib/python2.6/site-packages/requests/models.py", line 752, in generate
    raise ChunkedEncodingError(e)
ChunkedEncodingError: ("Connection broken: error(9, 'Bad file descriptor')", error(9, 'Bad file descriptor'))

Я думал, что могут быть зависания сокетов или файловых дескрипторов, но после часа работы процесса все ещетолько 4 открытых фдсЭто было трудно отладить, потому что это происходит так периодически.Я впервые использую библиотеку запросов.

Вот сокращенная версия кода, я оставил все запросы вызовов в одном месте:

payload = {
    'some_stuff': True,
}
enroll_url = 'https://foo.ca'
expected = '''some string'''

#use selenium to login and (critically) run js on homepage to generate cookies
#then quit selenium and use the cookies to setup a requests session
def login(username, password):
    <selenium code to login snipped>
    #retrieve all the cookies and kill webdriver since we don't need it anymore
    cookies = driver.get_cookies()
    driver.quit()

    s = requests.Session()

    for cookie in cookies:
        s.cookies.set(cookie['name'], cookie['value'])
        if(cookie['name'] == 'XSRF-TOKEN'):
            s.headers.update({
                'X-XSRF-TOKEN': cookie['value'],
                'Connection':'close',
            })
    return s

def attemptEnroll(session):
    if(session is None):
        return ""
    r = session.post(enroll_url, json=payload)
    return r.text

#number of failed attempts in a row
failed_count = 0
session = None
while True:
    worked = False
    errorMsg = "Unknown error"
    try:
        resp = attemptEnroll(session)
        worked = (resp == expected)
        errorMsg = resp
    except Exception, e:
        errorMsg = str(e) + traceback.format_exc()
    if(worked):
        failed_count = 0
        #wait 2-7 minutes between requests
        wait=randint(2*60,7*60)
        sleep(wait)        
    else:
        sleep(failed_count*60)            
        failed_count += 1
        #stop after 3 failures in a row
        if(failed_count >= 3):
            break       
        #otherwise create a new login and try again
        session = login("<snip>", "<snip>!")
...