2010-06-27 47 views
21

我真的很想弄清楚为什么这段代码在Python 2中工作,而不是在Python 3中工作。我只是想抓住一个json页面,然后解析它。下面是在Python 2代码:Python 2与Python 3 - urllib格式

import urllib, json 
response = urllib.urlopen("http://reddit.com/.json") 
content = response.read() 
data = json.loads(content) 

认为在Python 3的等效代码会是这样:

import urllib.request, json 
response = urllib.request.urlopen("http://reddit.com/.json") 
content = response.read() 
data = json.loads(content) 

但它在我的脸上吹了起来,因为读返回的数据( )是一个“字节”类型。然而,我无法将它转化为json能够解析的东西。我从reddit的试图发送UTF-8回我的头知道,但我似乎无法得到的字节解码成UTF-8:

import urllib.request, json 
response = urllib.request.urlopen("http://reddit.com/.json") 
content = response.read() 
data = json.loads(content.decode("utf8")) 

我在做什么错?

编辑:问题是我无法将数据转换为可用状态;即使json加载数据,但它的一部分是不可显示的,我希望能够将数据打印到屏幕上。

第二次编辑:这个问题似乎与分析有关,而不是解析。 Alex的答案通过将IO设置为utf8为脚本提供了一种在Python 3中工作的方式。但问题仍然存在:为什么代码在Python 2中运行,而不是在Python 3中运行?

回答

15

您发布的代码大概是由于错误的剪切和粘贴操作,因为它在两个版本中都显然是错误的(f.read()失败,因为没有定义f裸号)。

在Py3中,ur = response.decode('utf8')对我来说非常适合,下面的json.loads(ur)也是如此。也许错误的复制和粘贴会影响您的2到3次转换尝试。

+0

哎呀,我会解决代码错误...我试着重新格式化它的显示,但把它拧在过程中。 :P 无论如何,在解析数据后(使用简单的“打印(数据)”),我无法查看数据,因为它会给我带来charmap错误。 – 2010-06-28 00:08:02

+0

@Daniel,你收到数据后的问题似乎是一个单独的问题,从这个数据中获取数据(我的回答,看起来,回应 - 尽管看起来你不同意,因为你没有,我甚至不满意!)。如果'data'指的是'json.loads(response)',我可以'打印'它没有任何问题(在我的Mac Terminal.app,它支持UTF-8)。什么是你的sys.stdout.encoding?在启动Python 3之前,您是否正确设置了环境变量'PYTHONIOENCODING:Encoding [:errors]用于stdin/stdout/stderr'?等等 - 完全不同的问题,请参阅。 – 2010-06-28 01:26:41

+0

对不起,如果我一开始不清楚。核心问题是我不能在解析后使用数据,无论出于何种原因(打印只是它的开始;如果我不能打印它,那么我会遇到麻烦的地方读取数据)。我将检查编码,足以说它不适用于我的W7机器。 – 2010-06-28 13:17:03

0

请参阅that在另一个Unicode相关问题的答案。

现在:Python 3 str(它是Python 2 unicode)类型是一个理想化的对象,它处理的是“字符”而不是“字节”。为了用于/从磁盘/网络数据使用,这些字符需要通过“转换表”(也就是a.k.a编码a.k.a代码页)从字节进行编码/解码。由于操作系统的多样性,Python在历史上避免猜测编码应该是什么;这种情况多年来一直在发生变化,但仍然存在“面对模棱两可,拒绝猜测的诱惑”的原则。

谢天谢地,Web服务器使您的工作更轻松。以上你response应该给你所需要的所有额外信息:

>>> response.headers['content-type'] 
'application/json; charset=UTF-8' 

所以,每次发出对Web服务器的请求,检查一个字符集值的Content-Type头,并请求的数据进行解码转换成Unicode( Python 3:bytes.decode(charset)str)通过使用该字符集。

6

取决于您的Python版本,您必须选择正确的库。

为Python 3.5

import urllib.request 
data = urllib.request.urlopen(url).read().decode('utf8') 

为Python 2。7

import urllib 
url = serviceurl + urllib.urlencode({'sensor':'false', 'address': address}) 
uh = urllib.urlopen(url) 
+0

您可能想要提供解释来说明您的代码。 – GabrielOshiro 2015-10-27 00:53:16