2015-08-14 36 views
2

我想從位於某個URL的文件加載數據。我使用請求來獲取它(這發生得很快)。但是,使用r.json()格式化部分字典需要大約10分鐘的時間。我如何加快速度?使用.json格式化的性能問題()

match_list = [] 
for i in range(1, 11): 
    r = requests.get('https://s3-us-west-1.amazonaws.com/riot-api/seed_data/matches%d.json' % i) 
    print('matches %d of 10 loaded' % i) 
    match_list.append(r.json()['matches']) 
    print('list %d of 10 created' % i) 
match_histories = {} 
match_histories['matches'] = match_list 

我知道,有一個相關的問題在這裏:Performance problem transforming JSON data,但我不知道怎樣才能應用,爲我的情況。謝謝! (我正在使用Python 3)。

編輯:

我一直在考慮,似乎有前途的不少建議,但每次我打了一個路障。

  • 我想嘗試cjson,但我不能安裝它(PIP找不到微軟的Visual C++ 10.0,嘗試使用使用Lua的一些安裝,但我在我的道路需要CL開始)。

  • json.loads(r.content)導致在Python 3

  • 一個TypeError我不知道怎麼去ijson工作。

  • ujson似乎大概只要採取爲JSON

  • json.loads(r.text.encode( 'UTF-8')。解碼( 'UTF-8')),只需長太

+0

你確定這是json轉換專門需要時間嗎?當我嘗試這個時,我發現即使'r.content'也需要很長時間。從我看到的答覆內容大約是19MB。創建一個19MB的字符串需要很長時間,即使你不試圖將其解析爲json。 – BrenBarn

+0

呃,19MB是teensy。但我確實發現'json.load'不會將其視爲有效的JSON,因此'json.loads(r.content)'引發'UnicodeDecodeError:'utf8'編解碼器無法解碼位置0中的字節0xc3:無效的延續byte'。我敢打賭,'r.json()'在異常處理上花費了大量的時間。 –

+0

我不得不解碼數據爲unicode來處理它:'data = json.loads(r.text.encode('utf-8')。decode('utf-8'))' –

回答

5

內置的JSON解析器不是特別快。我嘗試另一種解析器,蟒蛇,cjson,像這樣:

import requests 
import cjson 

r = requests.get('https://s3-us-west-1.amazonaws.com/riot-api/seed_data/matches1.json') 
print cjson.decode(r.content) 

整個計劃花了3.7秒我的筆記本電腦,包括獲取數據和格式顯示輸出。

編輯:哇,我們都在錯誤的軌道上。 json不慢;請求的字符集檢測非常緩慢。試試這個:

import requests 
import json 

r = requests.get('https://s3-us-west-1.amazonaws.com/riot-api/seed_data/matches1.json') 
r.encoding = 'UTF-8' 
print json.loads(r.text) 

json.loads部分在我的同一檯筆記本電腦需要1.5秒。這仍然比cjson.decode慢(僅爲.62s),但速度可能會很快,以至於您不會在乎這是不是經常運行的東西。警告:我只在Python2上進行了基準測試,它在Python3上可能會有所不同。

編輯2:看來cjson不會在Python3中安裝。沒關係:json.loads在這個版本只需要0.54秒。字符集檢測仍然是冰河,儘管如此,評論r.encoding = 'UTF-8'仍然使測試腳本運行在O(永恆)時間。如果您可以指望那些始終採用UTF-8編碼的文件,我認爲性能祕訣就是將這些信息放入您的腳本中,以免在運行時弄清楚。通過這種提升,您無需費心提供自己的JSON解析器。只要運行:

import requests 

r = requests.get('https://s3-us-west-1.amazonaws.com/riot-api/seed_data/matches1.json') 
r.encoding = 'UTF-8' 
print r.json() 
+0

我被撕裂了!我想爲你展示cjson庫的答案+1,但我不想爲你的答案投票,因爲你沒有向他展示如何將數據編碼爲unicode。 –

+0

這個答案非常詳盡,謝謝。我在安裝cjson時遇到問題。我只是使用pip來安裝ijson ...但是它找不到cjson(對不起,我對編程有點新,並且不熟悉製作這種安裝的最佳方式)。 – Mark

+1

@nivixzixer Gah!多麼尷尬;你是對的。順便說一句,'r.text'是'r.content'的unicode版本。 @Mark(你究竟得到了*那個* username?!?)包名是整個字符串:python-cjson。像「pip install python-cjson」一樣安裝它。 –

0

我會推薦使用流式JSON解析器(看看ijson)。流式方法會提高解析步驟的內存效率,但是由於您在內存中存儲了一個相當大的數據集,因此您的程序可能仍然很慢。

0

那麼這是一個非常大的文件,你有那裏和純Python代碼(我懷疑請求庫不使用C綁定JSON解析)通常是相當緩慢。你真的需要所有的數據嗎?如果你只需要它的某些部分,也許你可以找到一個更快的方式來找到它或使用不同的API,如果它可用。

您也可以嘗試通過使用圖書館像ujson使用更快的JSON庫:https://pypi.python.org/pypi/ujson

我沒有嘗試這一個自己,但它聲稱要快。然後您可以撥打ujson.loads(r.text)來獲取您的數據。

0

它看起來像requests使用simplejson到JSON解碼。如果您只是獲得r.content的數據,然後使用內置Python json庫,則json.loads(r.content)的工作速度非常快。它通過爲無效的JSON引發錯誤而工作,但這比懸掛很長時間要好。

+0

json.loads(r.content)在設置r = requests.get(BLA ....)後立即導致TypeError:JSON對象必須是str,而不是'bytes'。 – Mark

+0

@Mark:推測你正在運行Python 3.在Python 2上不會發生該錯誤。 – BrenBarn