22

このコードがPython3ではなくPython2で機能する理由を理解しようとするのに本当にうんざりしています。私は、jsonのページを取得して解析しようとしているだけです。Python2のコードは次のとおりです。

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

Python3の同等のコードは次のようになると思いました。

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

しかし、read()によって返されるデータは「バイト」型であるため、私の顔には爆発します。しかし、私は一生の間、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がデータを読み込んでも一部が表示されないので、画面にデータを印刷できるようにしたいと思います。

2番目の編集:問題は構文解析よりも印刷に関係しているようです。Alexの回答は、IOをutf8に設定することにより、スクリプトがPython3で機能する方法を提供します。しかし、まだ疑問が残ります。コードがPython 2で機能したのに、Python3では機能しなかったのはなぜですか。

4

4 に答える 4

15

投稿するコードは、両方のバージョンで明らかに間違っているため、カットアンドペースト操作が間違っていることが原因である可能性があります(ベアネームが定義されf.read()ていないため失敗します)。f

Py3ではur = response.decode('utf8')、次のように、私にとっては完全にうまく機能しますjson.loads(ur)。間違ったコピーアンドペーストが2対3の変換の試みに影響を与えた可能性があります。

于 2010-06-28T00:06:03.280 に答える
7

Pythonのバージョンに応じて、正しいライブラリを選択する必要があります。

Python3.5の場合

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

Python2.7の場合

import urllib
url = serviceurl + urllib.urlencode({'sensor':'false', 'address': address})   
uh = urllib.urlopen(url)
于 2015-10-27T00:29:02.230 に答える
0

別のUnicode関連の質問でその回答を参照してください。

現在、Python 3 str(Python 2でしたunicode)タイプは、「バイト」ではなく「文字」を処理するという意味で、理想化されたオブジェクトです。これらの文字は、ディスク/ネットワークデータに使用したり、ディスク/ネットワークデータから使用したりするために、「変換テーブル」(コードページとも呼ばれる)によってバイトにエンコード(エンコード/デコード)する必要があります。オペレーティングシステムの多様性のために、Pythonは歴史的にそのエンコーディングがどうあるべきかを推測することを避けてきました。これは何年にもわたって変化してきましたが、それでも「あいまいさに直面して、推測する誘惑を拒否する」という原則があります。適用されます。

ありがたいことに、Webサーバーを使用すると作業が簡単になります。上記responseは、必要なすべての追加情報を提供するはずです。

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

したがって、Webサーバーにリクエストを発行するたびに、Content-Typeヘッダーで文字セット値を確認し、その文字セットを使用してリクエストのデータをUnicode(Python 3:bytes.decode(charset)str)にデコードします。

于 2011-10-17T00:10:45.433 に答える
0

これは、両方のバージョン間で互換性のあるアプローチです。最初にバイトデータを文字列に変換し、次に文字列をロードすることで機能します。

import json
try:
    from urllib.request import Request, urlopen #python3+
except ImportError:
    from urllib2 import Request, urlopen        #python2

url = 'https://jsonfeed.org/feed.json'
request = Request(url)
response_json_string = urlopen(request).read().decode('utf8')
response_json_object = json.loads(response_json_string)
于 2020-02-07T22:08:14.873 に答える