JSON ऑब्जेक्ट को बाइट स्वीकार करते हैं या urlopen आउटपुट स्ट्रिंग्स करते हैं


177

पायथन 3 के साथ मैं एक URL से एक json दस्तावेज़ का अनुरोध कर रहा हूँ।

response = urllib.request.urlopen(request)

responseवस्तु के साथ एक फ़ाइल जैसी वस्तु है readऔर readlineतरीकों। आम तौर पर एक JSON ऑब्जेक्ट को टेक्स्ट मोड में खोली गई फ़ाइल के साथ बनाया जा सकता है।

obj = json.load(fp)

मैं क्या करना चाहूंगा:

obj = json.load(response)

यह हालांकि काम नहीं करता है क्योंकि urlopen बाइनरी मोड में एक फ़ाइल ऑब्जेक्ट देता है।

चारों ओर एक काम है:

str_response = response.read().decode('utf-8')
obj = json.loads(str_response)

लेकिन यह बुरा लगता है ...

वहाँ एक बेहतर तरीका है कि मैं एक बाइट फ़ाइल ऑब्जेक्ट को एक स्ट्रिंग फ़ाइल ऑब्जेक्ट में बदल सकता हूं? या मैं किसी भी पैरामीटर याद कर रहा हूँ urlopenया json.loadएक एन्कोडिंग देने के लिए?


2
मुझे लगता है कि आपके पास वहां एक टाइपो है, "रीडॉल" को "पढ़ना" चाहिए?
बॉब योप्लेट

@ याकूबोपलिट मैं सहमत हूँ।
CaptainNemo

जवाबों:


79

HTTP बाइट्स भेजता है। यदि प्रश्न में संसाधन पाठ है, तो वर्ण एन्कोडिंग सामान्य रूप से निर्दिष्ट किया जाता है, या तो सामग्री-प्रकार HTTP शीर्ष लेख द्वारा या किसी अन्य तंत्र (एक RFC, HTML meta http-equiv, ...) द्वारा।

urllib पता होना चाहिए कि बाइट्स को एक स्ट्रिंग में कैसे सांकेतिक शब्दों में बदलना है, लेकिन यह बहुत ही भोला है - यह एक बहुत ही कमजोर और बिना पायथोनिक लाइब्रेरी है।

पायथन 3 में डुबकी स्थिति के बारे में एक सिंहावलोकन प्रदान करता है।

आपका "वर्क-अराउंड" ठीक है - हालांकि यह गलत लगता है, यह इसे करने का सही तरीका है।


6
यह करने के लिए "सही" तरीका हो सकता है लेकिन अगर एक चीज थी जो मैं पायथन 3 के बारे में पूर्ववत कर सकता था तो यह इस बाइट्स / स्ट्रिंग्स बकवास होगी। आपको लगता है कि अंतर्निहित लाइब्रेरी फ़ंक्शंस कम से कम अन्य अंतर्निहित लाइब्रेरी फ़ंक्शंस से निपटना जानते हैं। हम अजगर का उपयोग करने वाले कारण का एक हिस्सा सरल सहज वाक्य रचना है। यह परिवर्तन उस सारे स्थान को तोड़ देता है।
ThatAintWorking

4
की जाँच करें "अनुरोध" पुस्तकालय - यह पूर्ण रूप से अपने आप के लिए बात की इस तरह संभालती है।
offby1

2
यह अन्य कार्यों से निपटने के लिए "कैसे पता है" की जरूरत में निर्मित पुस्तकालय कार्यों का मामला नहीं है। JSON को वस्तुओं के UTF-8 प्रतिनिधित्व के रूप में परिभाषित किया गया है, इसलिए यह जादुई रूप से बाइट्स को डिकोड नहीं कर सकता है कि यह एन्कोडिंग को नहीं जानता है। मैं मानता हूं कि urlopenबाइट्स को डिकोड करने में सक्षम होना चाहिए क्योंकि यह एन्कोडिंग जानता है। वैसे भी, मैंने एक उत्तर के रूप में पायथन मानक पुस्तकालय समाधान पोस्ट किया है - आप codecsमॉड्यूल का उपयोग करके बाइट्स की स्ट्रीमिंग डिकोडिंग कर सकते हैं ।
jbg

1
@ThatAintWorking: मैं असहमत होगा। हालांकि यह गर्दन में दर्द है बाइट्स और स्ट्रिंग्स के बीच अंतर को स्पष्ट रूप से प्रबंधित करने के लिए, यह आपके लिए कुछ अंतर्निहित रूपांतरण करने के लिए बहुत अधिक दर्द है। अंतर्निहित बाइट्स <-> स्ट्रिंग रूपांतरण कई बग्स का स्रोत हैं, और पायथन 3 नुकसान की ओर इशारा करने में बहुत सहायक है। लेकिन मैं मानता हूं कि पुस्तकालय में इस क्षेत्र में सुधार की गुंजाइश है।
EvertW

@ मेरी विफलता में, मेरी राय में, यह पहली जगह में यूनिकोड होने के लिए मजबूर करता है।
ThatAintWorking

99

बचाव के लिए पायथन का अद्भुत मानक पुस्तकालय ...

import codecs

reader = codecs.getreader("utf-8")
obj = json.load(reader(response))

Py2 और py3 दोनों के साथ काम करता है।

डॉक्स: अजगर 2 , python3


11
मुझे यह त्रुटि मिली जब इस उत्तर को python 3.4.3सुनिश्चित करने की कोशिश में क्यों? त्रुटि थीTypeError: the JSON object must be str, not 'StreamReader'
हारून लेलेयर

9
@ AronYsidoro क्या आपने संभवतः json.loads()इसके बजाय उपयोग किया था json.load()?
स्लीपाइकल

6
बोनस अंक के लिए, utf-8 मानने के बजाय, प्रतिक्रिया में निर्दिष्ट एन्कोडिंग का उपयोग करें response.headers.get_content_charset():। Noneअगर कोई एन्कोडिंग नहीं है, तो वापस लौटता है और python2 पर मौजूद नहीं है।
फिल फ्रॉस्ट

5
@PhilFrost यह चालाक है। व्यवहार में यह उस से सावधान रहने के लिए भुगतान कर सकता है; JSON हमेशा परिभाषा द्वारा UTF-8, UTF-16 या UTF-32 (और UTF-8 होने की संभावना है), इसलिए यदि वेब सर्वर द्वारा एक और एन्कोडिंग लौटाया जाता है, तो संभवतः यह वेब सर्वर सॉफ़्टवेयर की बजाय एक गलत धारणा है वास्तव में गैर-मानक JSON।
jbg

6
जब मैंने अजगर 3.5 में उपयोग किया था, तो त्रुटि "एट्रीब्यूटरोर: 'बाइट्स' ऑब्जेक्ट की कोई विशेषता नहीं है 'पढ़ें"
हार्पर कू

66

मुझे लगता है कि सवाल का सबसे अच्छा जवाब है :)

import json
from urllib.request import urlopen

response = urlopen("site.com/api/foo/bar").read().decode('utf8')
obj = json.loads(response)

18

requestsपुस्तकालय का उपयोग कर इसे हल करने की कोशिश कर रहे किसी और के लिए :

import json
import requests

r = requests.get('http://localhost/index.json')
r.raise_for_status()
# works for Python2 and Python3
json.loads(r.content.decode('utf-8'))

12
यह कार्यक्षमता अंतर्निहित है requests: आप बस कर सकते हैंr.json()
jbg

1
स्पष्ट करें, यदि आप @ jbg की विधि का उपयोग करते हैं, तो आपको करने की आवश्यकता नहीं है json.loads। आपको बस इतना करना है r.json()और आपने अपनी JSON वस्तु को पहले से ही एक डिक्टेट में लोड कर लिया है।
ब्लेयरग 23

*** UnicodeEncodeError: 'ascii' codec can't encode characters in position 264-265: ordinal not in range(128)
andilabs

13

यह मेरे लिए काम करता है, मैंने मनुष्यों के अनुरोधोंjson() में डॉक्टर की जाँच के साथ 'अनुरोध' पुस्तकालय का उपयोग किया

import requests

url = 'here goes your url'

obj = requests.get(url).json() 

यह सबसे अच्छा तरीका है। वास्तव में पठनीय, और जो कोई भी ऐसा कुछ कर रहा है उसके पास अनुरोध होना चाहिए।
बाल्ड्रिक

6

मैं पायथन 3.4.3 और 3.5.2 और Django 1.11.3 का उपयोग करके समान समस्याओं में भाग गया। हालाँकि, जब मैंने अजगर 3.6.1 में अपग्रेड किया तो समस्याएं दूर हो गईं।

आप इसके बारे में और अधिक यहाँ पढ़ सकते हैं: https://docs.python.org/3/whatsnew/3.6.html#json

यदि आप पायथन के एक विशिष्ट संस्करण से बंधे नहीं हैं, तो बस 3.6 या बाद के उन्नयन पर विचार करें।


3

यदि आप फ्लास्क माइक्रोफ़्रामवर्क का उपयोग करते हुए इस समस्या का सामना कर रहे हैं, तो आप बस कर सकते हैं:

data = json.loads(response.get_data(as_text=True))

डॉक्स से : "अगर as_text को True पर सेट किया जाता है तो रिटर्न वैल्यू एक डिकोडेड यूनिकोड स्ट्रिंग होगा"


मुझे यह पृष्ठ इसलिए मिला क्योंकि मैं फ्लास्क यूनिट परीक्षणों के साथ एक समस्या थी - सिंगल लाइन कॉल पोस्ट करने के लिए धन्यवाद।
sfblackl

1

आपके वर्कअराउंड ने वास्तव में मुझे बचा लिया। मुझे फाल्कन फ्रेमवर्क का उपयोग करते हुए अनुरोध को संसाधित करने में बहुत समस्या हो रही थी। इसने मेरे लिए काम किया। अनुरोध प्रपत्र कर्ल पीआर httpie req जा रहा है

json.loads(req.stream.read().decode('utf-8'))

1

यह बाइट डेटा को json में स्ट्रीम करेगा।

import io

obj = json.load(io.TextIOWrapper(response))

io.TextIOWrapper कोडेक के मॉड्यूल रीडर के लिए पसंद किया जाता है। https://www.python.org/dev/peps/pep-0400/


`*** विशेषता: 'रिस्पांस' ऑब्जेक्ट में कोई विशेषता नहीं है '
पठनीय'`


क्या आप urllib या अनुरोधों का उपयोग कर रहे हैं? यह urllib के लिए है। यदि आपके पास बाइट्स ऑब्जेक्ट है, तो बस उपयोग करें json.loads(bytes_obj.decode())
कोलिन एंडरसन

0

बस इस सरल विधि को एक JSON के रूप में HttpResponse सामग्री बनाने के लिए मिला

import json

request = RequestFactory() # ignore this, this just like your request object

response = MyView.as_view()(request) # got response as HttpResponse object

response.render() # call this so we could call response.content after

json_response = json.loads(response.content.decode('utf-8'))

print(json_response) # {"your_json_key": "your json value"}

आशा है कि आपकी मदद करता है


0

Python 3.6 के रूप में, आप json.loads()किसी bytesऑब्जेक्ट को सीधे डिस्क्राइब करने के लिए उपयोग कर सकते हैं (एन्कोडिंग UTF-8, UTF-16 या UTF-32 होनी चाहिए)। इसलिए, मानक पुस्तकालय से केवल मॉड्यूल का उपयोग करके, आप कर सकते हैं:

import json
from urllib import request

response = request.urlopen(url).read()
data = json.loads(response)

-2

मैं का उपयोग करने के लिए नीचे कार्यक्रम का इस्तेमाल किया json.loads()

import urllib.request
import json
endpoint = 'https://maps.googleapis.com/maps/api/directions/json?'
api_key = 'AIzaSyABbKiwfzv9vLBR_kCuhO7w13Kseu68lr0'
origin = input('where are you ?').replace(' ','+')
destination = input('where do u want to go').replace(' ','+')
nav_request = 'origin={}&destination={}&key={}'.format(origin,destination,api_key)
request = endpoint + nav_request
response = urllib.request.urlopen(request).read().decode('utf-8')
directions = json.loads(response)
print(directions)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.