python请求对于带有wsgi的apache的https不起作用

时间:2013-07-02 01:06:42

标签: python django python-requests

当我尝试使用请求加载外部URL的django视图时,我得到一个'module'对象没有属性'create_connection'。但是,当我使用urllib2或来自交互式shell的相同请求代码时,它可以工作。

我的环境:

  • Python 2.5.2
  • 请求0.10.0(我使用的是需要此版本的第三方API)
  • 在我的django网站的virtualenv中使用WSGI的Apache
  • Django 1.4.1
  • Debian Linux 5
  • 我没有SELinux(或任何类似的安全性)

我实际上使用2种不同的API来完成不同的功能。他们都需要请求,他们都提出了这个错误:

Exception Type: AttributeError
Exception Value: 'module' object has no attribute 'create_connection'
Exception Location: /my/virtualenv/dir/lib/python2.5/site-packages/requests/packages/urllib3/connectionpool.py in connect, line 67

例外中提到的行是:

sock = socket.create_connection((self.host, self.port), self.timeout)

看起来python 2.5附带的socket版本没有create_connection方法(它在2.6中添加)。但是,我尝试从virtualenv中的python交互式shell运行完全相同的代码,一切正常。另外,请求0.10.0应该与python 2.5一起使用。

我创建了以下2个测试视图,因为我怀疑请求是问题的一部分:

def get_requests(request):
    import requests
    r = requests.get("https://google.ca")
    return HttpResponse(r.text)

def get_urllib(request):
    import urllib2
    r = urllib2.urlopen('https://google.ca')
    return HttpResponse(r.read())

urllib视图有效,请求视图给出了与上面相同的错误。

urllib工作的事实向我表明Apache有权连接到互联网(这不是防火墙问题)。

我在尝试查看时已经完成了tcpdump,并且请求甚至都没有尝试连接。

有什么想法吗?请不要建议使用除请求之外的其他内容,因为我使用了2个不同的第三方API。

感谢。

4 个答案:

答案 0 :(得分:1)

在使用安装了ssl模块的Python 2.5中的HTTPS中,看起来您遇到了请求0.10.0(或者,实际上是在urllib3中)中的错误。

如果您浏览0.10.0 source,则可以看到如果安装了ssl并且您发出了HTTPS请求,那么您将转到VerifiedHTTPSConnection.connect方法。 HTTPSConnectionPool来源的评论中也对此进行了解释。但是你甚至不需要追踪源代码,因为你已经从追溯中看到了这一点。

如果您查看the source该方法,它会无条件地调用socket.create_connection,这可以保证在2.5中失败。

任何人都有可能修复这个错误的可能性非常小。看起来它是在0.10.0中引入的,而0.10.1只是通过降低2.5支持来解决它。 (我对此并不积极,因为我无法在错误跟踪器中找到它。)

那么,你能做些什么呢?

首先,请注意,虽然create_connectionconnect“更高级别”,但只有在确定要创建哪种类型的套接字之前,它才进行名称查找。如果您知道自己只关心IPv4,可以将其替换为:

self.sock = socket.socket()
self.sock.settimeout(self.timeout)
self.sock.connect((self.host, self.port))

如果你关心IPv6,你可以借用create_connection代替urllib3.connectionpool.VerifiedHTTPConnection.connect

所以,你有几个选择:

  • 分叉源代码并修补create_connection以使用变通方法代替urllib3.connectionpool.VerifiedHTTPConnection.connect
  • Monkeypatch socket在运行时。
  • Monkeypatch create_connection在运行时添加{{1}}实现。

但是,鉴于历史,我不想保证0.10.0不会有Python 2.5的进一步问题。

答案 1 :(得分:0)

从0.10.1开始,请求放弃了对Python 2.5的支持。

升级您的Python或使用请求0.10.0版本的请求。

  

0.10.1(2012-01-23)

     

PYTHON 3支持!下降2.5支持。 (向后不兼容)

答案 2 :(得分:0)

使用请求0.9.3。这对Python 2.5肯定有用。我们需要Python 2.5支持,并且Kenneth告诉我们使用该版本,或者这是我们发现的最新版本,它实际上在实践中有效。如果您需要返回使用该版本,请注意任何API差异。

答案 3 :(得分:0)

as abarnert pointed out,这是由请求0.10.0中的错误引起的,并且由于在版本0.10.1中删除了python 2.5支持,因此无法修复。

所以我编辑了这个文件requests / packages / urllib3 / connectionpool.py(第67行)。

原始行:

    sock = socket.create_connection((self.host, self.port), self.timeout)

我将其替换为:

    try:
        sock = socket.create_connection((self.host, self.port), self.timeout)
    except AttributeError:
        # python 2.5 fix
        sock = socket.socket()
        if self.timeout is not None:
            sock.settimeout(self.timeout)
        sock.connect((self.host, self.port))

通过此更改,一切正常。