【问题标题】:xml get using requests library results in exception使用请求库的 xml 获取导致异常
【发布时间】:2017-10-13 16:22:45
【问题描述】:

我是 Python 编程新手,曾尝试研究我的问题,但目前还没有找到解决方案。我希望有人可以提供帮助。

我有一个脚本可以对用于激活或停用网络中继开关的 IP 地址进行 http get 调用。代码的相对部分如下所示:

import requests
r = requests.get('http://192.168.1.100/state.xml?relayState=1&noReply=0')

上面成功打开了网络中继开关,但是来自网络中继的响应导致如下所示的一些异常消息,并且脚本停止执行。为了我的脚本的目的,我不需要处理任何响应,但如果我需要为了使脚本正常运行,我会的。我的预感是问题围绕使用 xml 版本 1.0 而不是 1.1 的 Web 中继开关。我还没有找到强制请求使用 1.0 的方法。我正在使用 Python 3.6.1

Traceback (most recent call last):
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\requests\packages\urllib3\connectionpool.py", line 600, in urlopen
    chunked=chunked)
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\requests\packages\urllib3\connectionpool.py", line 386, in _make_request
    six.raise_from(e, None)
  File "<string>", line 2, in raise_from
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\requests\packages\urllib3\connectionpool.py", line 382, in _make_request
    httplib_response = conn.getresponse()
  File "C:\Program Files (x86)\Python36-32\lib\http\client.py", line 1331, in getresponse
    response.begin()
  File "C:\Program Files (x86)\Python36-32\lib\http\client.py", line 297, in begin
    version, status, reason = self._read_status()
  File "C:\Program Files (x86)\Python36-32\lib\http\client.py", line 279, in _read_status
    raise BadStatusLine(line)
http.client.BadStatusLine: <?xml version='1.0' encoding='utf-8'?>



During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\requests\adapters.py", line 423, in send
    timeout=timeout
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\requests\packages\urllib3\connectionpool.py", line 649, in urlopen
    _stacktrace=sys.exc_info()[2])
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\requests\packages\urllib3\util\retry.py", line 347, in increment
    raise six.reraise(type(error), error, _stacktrace)
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\requests\packages\urllib3\packages\six.py", line 685, in reraise
    raise value.with_traceback(tb)
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\requests\packages\urllib3\connectionpool.py", line 600, in urlopen
    chunked=chunked)
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\requests\packages\urllib3\connectionpool.py", line 386, in _make_request
    six.raise_from(e, None)
  File "<string>", line 2, in raise_from
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\requests\packages\urllib3\connectionpool.py", line 382, in _make_request
    httplib_response = conn.getresponse()
  File "C:\Program Files (x86)\Python36-32\lib\http\client.py", line 1331, in getresponse
    response.begin()
  File "C:\Program Files (x86)\Python36-32\lib\http\client.py", line 297, in begin
    version, status, reason = self._read_status()
  File "C:\Program Files (x86)\Python36-32\lib\http\client.py", line 279, in _read_status
    raise BadStatusLine(line)
requests.packages.urllib3.exceptions.ProtocolError: ('Connection aborted.', BadStatusLine("<?xml version='1.0' encoding='utf-8'?>\r\n",))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "E:/Software/Python/test3.py", line 3, in <module>
    r = requests.get('http://192.168.1.100/state.xml?relayState=1')
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\requests\api.py", line 70, in get
    return request('get', url, params=params, **kwargs)
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\requests\api.py", line 56, in request
    return session.request(method=method, url=url, **kwargs)
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\requests\sessions.py", line 488, in request
    resp = self.send(prep, **send_kwargs)
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\requests\sessions.py", line 609, in send
    r = adapter.send(request, **kwargs)
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\requests\adapters.py", line 473, in send
    raise ConnectionError(err, request=request)
requests.exceptions.ConnectionError: ('Connection aborted.', BadStatusLine("<?xml version='1.0' encoding='utf-8'?>\r\n",))
>>> 

【问题讨论】:

    标签: xml python-3.x python-requests


    【解决方案1】:

    您确定网址应该是 http 而不是 https?这是某人的问题:Python requests.exception.ConnectionError: connection aborted "BadStatusLine"

    否则,异常意味着错误来自服务器的响应,我假设您无法控制。您可以与控制它的任何人一起打开支持票证,或者,如果您赶时间,您可以通过捕获并忽略异常来解决它,这很骇人听闻,但您可能可以接受,因为您不需要响应并且知道您的请求在另一端是成功的:

    try:
        requests.get('http://192.168.1.100/state.xml?relayState=1&noReply=0')
    except requests.exceptions.ConnectionError as err:
        if "BadStatusLine" in repr(err):
            # TODO: be a responsible developer and figure out why I get BadStatusLine
            pass
        else:
            # wasn't the error I was expecting, so raise it
            raise
    

    对于生产代码,我想找出错误的根源,但在开发过程中,我可能愿意执行以下操作,以便继续前进。

    【讨论】:

    • 我确定是http。我注意到当我在浏览器中输入相同的命令时,它返回:这个 XML 文件似乎没有任何与之关联的样式信息。那是问题吗?我尝试了您的代码,得到的结果与之前的尝试相同,但它有以下附加错误消息。 中的文件“E:\Software\Python\test3.py”,第 5 行,除了 http.client.BadStatusLine: NameError: name 'http' is not defined 我可以使用有效的“hacky”代码,但如果我有一些帮助,我也愿意解决这个问题以获得最终解决方案。
    • 该错误告诉您需要导入 http 模块。把它放在文件的顶部:import http(见上面的编辑代码)
    • 浏览器中的样式消息无关紧要,这只是您的浏览器告诉您 XML 没有引用任何 XSLT 样式表。
    • 我添加了导入 http 行,但仍然收到错误消息。挑选出错误消息中最重要的部分对我来说有点困难,但我认为以下是让我感到困惑的原因。
    • 文件“C:\Program Files (x86)\Python36-32\lib\http\client.py”,第 279 行,_read_status raise BadStatusLine(line) http.client.BadStatusLine: xml version='1.0' encoding='utf-8'?> raise BadStatusLine(line) requests.packages.urllib3.exceptions.ProtocolError: ('Connection aborted.', BadStatusLine("\r\n",)) raise ConnectionError(err, request=request) requests.exceptions.ConnectionError: ('Connection aborted.', BadStatusLine("\r\n",))
    【解决方案2】:

    我是上述网络继电器开关产品制造商的技术支持专家。最近的一封支持电子邮件提到了此线程,我认为为可能遇到此问题的任何其他人添加信息会很好。

    很久以前设计的几个旧模块硬件资源有限,不支持 XML 响应的完整 HTML 标头。

    几年前,这些产品使用更新的硬件进行了重新设计。出于向后兼容性的原因,/state.xml 响应仍然没有完整的 HTML 标头来适应那些为旧硬件系列开发软件的人。

    较新的产品现在支持完整的 HTML 标头,但必须提出不同的请求 - /stateFull.xml。

    原始示例的正确代码如下:

    import requests
    r = requests.get('http://192.168.1.100/stateFull.xml?relayState=1&noReply=0')
    

    注意:第一次提交到 StackOverflow,所以对于错过任何通常遵循的约定,我深表歉意。

    【讨论】:

    • 谢谢我在向我的 WebRelay Quad 发送请求时遇到问题,这解决了它!
    猜你喜欢
    • 2012-09-05
    • 1970-01-01
    • 2012-05-15
    • 2012-10-01
    • 2014-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多