Python 系统调用中断时重试时出现问题
我最近在工作中遇到了一个问题,由于系统调用中断,内部网站无法加载,我们遇到了间歇性问题。我们正在使用urllib2访问该网站。我不能分享确切的代码,但我们基本上是这样做的:Python 系统调用中断时重试时出现问题,python,Python,我最近在工作中遇到了一个问题,由于系统调用中断,内部网站无法加载,我们遇到了间歇性问题。我们正在使用urllib2访问该网站。我不能分享确切的代码,但我们基本上是这样做的: payload = {'userName': user_name, 'emailAddress': email_address, 'password': password} headers = {'Accept': 'application/json', 'C
payload = {'userName': user_name,
'emailAddress': email_address,
'password': password}
headers = {'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': token}
values = json.dumps(payload)
req = urllib2.Request(url, values, headers)
try:
response = urllib2.urlopen(req, timeout=30)
break
except IOError, e:
if e.errno != errno.EINTR:
print e.errno
raise
我们记录错误和引发的异常。例外情况是:
IOError: <urlopen error [Errno 4] Interrupted system call>
IOError:
错误号为None
。我以为是4点
在Python2.7中是否有更好的方法捕获此错误?我知道PEP475,但是我们现在不能升级到Python 3。代码表明它实际上是一个urleror
源代码,它的子类是IOError
,但处理参数的方式完全不同。这就是属性errno
和strerror
未初始化的原因。它同时传递字符串作为原因:
raise URLError("qop '%s' is not supported." % qop)
并包装来自其他来源的例外:
try:
h.request(req.get_method(), req.get_selector(), req.data, headers)
except socket.error, err: # XXX what error?
h.close()
raise URLError(err)
这就是为什么在通常的地方找不到errno:
>>> try:
urlopen('http://asdf')
except URLError, e:
pass
...
>>> e
URLError(gaierror(-2, 'Name or service not known'),)
>>> e.errno
>>> e.reason
gaierror(-2, 'Name or service not known')
>>> e.reason.errno
-2
这在本例中有效,但原因属性可以是字符串或socket.error
,这将导致错误
urllib2.py中URLError
的定义:
到底是哪一个python 2
socket.error
s在某个点被更改为subclassIOError
,这会对参数传递和错误的结果属性值造成严重破坏。我们使用的是Python 2.7,可能就是它,或者至少是相关的。我查看了URLError
的源代码,但没有意识到需要首先检查该错误。我试试看。验证可能需要一段时间,因为我仍然不确定引发错误的是否是网站。您的代码比我们的代码简洁得多,但基本相同。我们只是添加了很多日志记录。如果这种方法有效,我将对其进行重构,使其更加清晰
class URLError(IOError):
# URLError is a sub-type of IOError, but it doesn't share any of
# the implementation. need to override __init__ and __str__.
# It sets self.args for compatibility with other EnvironmentError
# subclasses, but args doesn't have the typical format with errno in
# slot 0 and strerror in slot 1. This may be better than nothing.
def __init__(self, reason):
self.args = reason,
self.reason = reason
def __str__(self):
return '<urlopen error %s>' % self.reason
while True: # or some amount of retries
try:
response = urllib2.urlopen(req, timeout=30)
break
except URLError, e:
if getattr(e.reason, 'errno', None) == errno.EINTR:
# Retry
continue