Python脚本在localhost gae开发服务器的urlopen后无法read() -- 连接被重置
我在本地运行Google App Engine的开发服务器(Java)。我想用Python 2.7的urllib.urlopen来获取一个网址。第一次获取是成功的,但当我尝试调用read()或readlines()时,出现了:
Traceback (most recent call last):
File "./getMap.py", line 6, in <module>
lst = f.readlines()
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 513, in readlines
line = self.readline()
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 445, in readline
data = self._sock.recv(self._rbufsize)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/httplib.py", line 552, in read
s = self.fp.read(amt)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 378, in read
data = self._sock.recv(left)
socket.error: [Errno 54] Connection reset by peer
浏览器和wget都能正常工作。问题出现在urllib和urllib2上。以下是我的代码:
import urllib2
f = urllib2.urlopen("http://localhost:8080/default.jsp")
lst = f.readlines()
for a in lst:
print a
奇怪的是,我可以用readline()打印出文件的第一行——但就是不能获取整个文件。我感觉可能是Python在“懒惰”地不请求整个网址的内容,直到我通过readlines()请求它,而这时开发服务器可能已经过于主动地关闭了连接。不过我也可能完全错了。
我试着研究这个问题,但没有找到相关的解决方案。我在谷歌上看到的大多数信息都是关于随机的、间歇性的时序问题(但这不是间歇性的问题,它是可靠的)或者代理/防火墙问题(这里没有这样的情况)。
假设我的理论是正确的——有没有办法告诉urlopen立刻获取整个响应,就像wget和浏览器那样?或者有没有办法让GAE开发服务器放松点,不要这么快就关闭连接?如果不必要的话,我不想深入到更底层的Python socket内容。
谢谢
附言:澄清一下:这个Python脚本只是从命令行运行,试图连接到同一台机器上的GAE开发服务器。我并不是想从GAE开发服务器连接到自己或者其他奇怪的东西,GAE服务器是运行Java的,而不是Python。我实际上想做的是:我的GAE网络应用有一些网络服务,我正在写一个批处理脚本来获取/发送数据到这些网络服务,这样当我需要重置/清空数据存储(例如:数据损坏)时,我可以先用这个Python脚本备份数据,然后再清空数据存储,最后再用这个脚本把数据加载回来。
更新:我又做了一些测试。Python读取GAE开发服务器提供的任何HTML文件都没有问题。然而,任何JSP文件,即使是最简单的“hello world” JSP,也会出现同样的“连接被对方重置”的错误。我会尝试更新到GAE SDK的1.6.1版本,反正我总得在某个时候更新,不如现在就做。希望这能解决问题。
2 个回答
显然我来得有点晚,但我也遇到了同样的问题,我通过把urllib换成httplib解决了这个问题:
import httplib
conn = httplib.HTTPConnection('localhost:8080')
# get the current image and save to file
url = 'default.jsp'
conn.request("GET", url)
response = conn.getresponse()
if response.status == 404:
return None
img_file = open("out.jpg",'wb')
img_file.write(response.read())
img_file.close()
response.close()
conn.close()
我不知道为什么这样有效,我只能猜测httplib的表现比urllib稍微好一些。
虽然我看不出你的Python代码有什么问题,也不知道你的Java GAE设置可能出什么问题,但我想给你提供一个不同的思路。
你提到你基本上想要向服务器发送GET/POST请求,并保存或稍后读取内容,而像wget这样的命令行工具可以正常工作。我建议你使用一个bash脚本,结合curl和Python,这样在需要进行更复杂的文本编辑时会更方便。
curl http://localhost:8080/default.jsp > default.bak
... wipe db ...
data = $(cat default.bak)
curl -X "POST" -d "backup=$data" http://localhost:8080/default_restore.jsp
如果你需要在发送数据之前进行编辑,可以使用Python从default.bak文件读取数据,或者通过管道将数据传递给标准输入。
data = $(cat default.bak)
python your_script.py $data
curl http://localhost:8080/default.jsp | python yourscript.py > default.bak