python CSV、JSON文件讀寫及pickle序列化使用筆記

 

一、CSV使用

1 CSV文件讀取

逗號分隔值(Comma-Separated Values,CSV,有時也稱爲字符分隔值,因爲分隔字符也可以不是逗號),其文件以純文本形式存儲表格數據(數字和文本)。純文本意味着該文件是一個字符序列,不含必須像二進制數字那樣被解讀的數據。

假設現在有筆資料檔案(jamesbond.csv),Film,Year,Actor,Director,Box Office,Budget,Bond Actor Salaryheader,其餘爲資料內容,如下:

Film,Year,Actor,Director,Box Office,Budget,Bond Actor Salary
Dr. No,1962,Sean Connery,Terence Young,448.8,7,0.6
From Russia with Love,1963,Sean Connery,Terence Young,543.8,12.6,1.6
Goldfinger,1964,Sean Connery,Guy Hamilton,820.4,18.6,3.2
Thunderball,1965,Sean Connery,Terence Young,848.1,41.9,4.7
...

接着用open()開啓它,並用csv.reader()返回一個reader對象,利用該對象遍歷csv文件中的行:

import csv
with open('jamesbond.csv') as f:
    myCsv = csv.reader(f)
    headers = next(myCsv)
    ...

next()函數返回迭代器中的下一項。您可以添加一個默認的返回值,以在迭代結束時返回。

這裏next()用來讀取下一行的資料,而csv的第一行爲header

********************************************************************************************************************************************

這裏詳細說明一下next()的作用,相當於將迭代器iterator中的指針向後移動,將已經輸出的元素pop掉。

比如:

a=iter(['Numer',1,2,3,4]

first_element=next(a)  #此時first_element=‘Numer’

for i in a:
    print(a)
#輸出:
    1
    2
    3
    4

********************************************************************************************************************************************

for循環讀取csv每一行的資料:

import csv
with open('jamesbond.csv') as f:
    myCsv = csv.reader(f)
    headers = next(myCsv)  #讀取首行
    for row in myCsv:
        print(row)

可以看到每次輸出rowlist的資料型態:

'Dr. No', '1962', 'Sean Connery', 'Terence Young', '448.8', '7', '0.6']
['From Russia with Love', '1963', 'Sean Connery', 'Terence Young', '543.8', '12.6', '1.6']
['Goldfinger', '1964', 'Sean Connery', 'Guy Hamilton', '820.4', '18.6', '3.2']
['Thunderball', '1965', 'Sean Connery', 'Terence Young', '848.1', '41.9', '4.7']

因此,可以用讀取list的方式分別讀取裏面的值,像是row[0]讀取Film的資料,這裏就自己嘗試看看吧!

還有另外一種讀取方式的方法,可以將資料轉爲Dictionary格式:

import csv
with open('./jamesbond.csv') as f:
    myCsvDic = csv.DictReader(f)
    for row in myCsvDic:
        print(row['Film'])

print(row)可以看到像是OrderedDict([('Film', 'Dr. No'), ('Year', '1962'), ('Actor', 'Sean Connery'), ('Director', 'Terence Young'), ('Box Office', '448.8'), ('Budget', '7'), ('Bond Actor Salary', '0.6')])的內容,可以看到它是一個OrderedDict的物件型態,可以用取得Dictionary Value的方式取值,key就是header,上面範例中我們取每行row的Film

2 CSV文件寫入

前面都是說明如何讀取,現在,就要說明寫的部分了!

  • 首先先定義要寫入的資料,一般來說,csv需要第一行一行header來定義有哪些column,用list的格式儲存有哪些欄位。
  • 每一行rowtuple的方式並全部放在一個list裏面。
  • 我們就以剛剛的資料來當範例,如下:
headers = ['Film', 'Year', 'Actor', 'Director', 'Box Office', 'Budget', 'Bond Actor Salary']
rows = [('Film', 'Dr. No'), ('Year', '1962'), ('Actor', 'Sean Connery'), ('Director', 'Terence Young'), ('Box Office', '448.8'), ('Budget', '7'), ('Bond Actor Salary', '0.6'),
         ('Film', 'From Russia with Love'), ('Year', '1963'), ('Actor', 'Sean Connery'), ('Director', 'Terence Young'), ('Box Office', '543.8'), ('Budget', '12.6'), ('Bond Actor Salary', '1.6'),
         ('Film', 'Goldfinger'), ('Year', '1964'), ('Actor', 'Sean Connery'), ('Director', 'Guy Hamilton'), ('Box Office', '820.4'), ('Budget', '18.6'), ('Bond Actor Salary', '3.2'),]

再來就是寫入檔案了,先用writer(),先寫入第一行headers,再把資料內容rows寫入:

with open('writedFile.csv','w') as f:
    writeCsv = csv.writer(f)
    writeCsv.writerow(headers)
    writeCsv.writerows(rows)

除了上面的方式,也可以使用DictWriter(),直接定義headers並可以將資料以Dictionary方式寫入。只要將所有的資料(dic)存在一個list內,用writerows()

rows = [{'Film':'Dr. No','Year': '1962', 'Actor': 'Sean Connery', 'Director': 'Terence Young', 'Box Office': '448.8', 'Budget':'7', 'Bond Actor Salary': '0.6'},
         {'Film': 'From Russia with Love', 'Year': '1963', 'Actor': 'Sean Connery', 'Director': 'Terence Young', 'Box Office': '543.8', 'Budget': '12.6', 'Bond Actor Salary': '1.6'},
         {'Film': 'Goldfinger', 'Year': '1964', 'Actor': 'Sean Connery', 'Director': 'Guy Hamilton', 'Box Office': '820.4', 'Budget': '18.6', 'Bond Actor Salary': '3.2'}]

with open('writedFile.csv','w') as f:
    writedCsv = csv.DictWriter(f, headers)
    writedCsv.writeheader()
    writedCsv.writerows(rows)

3 分隔符

這裏說明一下dialect,編碼風格,默認爲逗點(,)分隔,不過也支援自定義,只要透過register_dialect方法。

register_dialect()

  • delimiter : 分隔符號,默認爲逗號。
  • name : 爲dialect的名稱
csv.register_dialect('myDialect', delimiter='|', quoting=csv.QUOTE_ALL)

範例:

  • 建立一個myTextFile.csv檔案,內容:
Film|Year|Actor|Director|Box Office|Budget|Bond Actor Salary
Dr. No|1962|Sean Connery|Terence Young|448.8|7|0.6
From Russia with Love|1963|Sean Connery|Terence Young|543.8|12.6|1.6
Goldfinger|1964|Sean Connery|Guy Hamilton|820.4|18.6|3.2
  • 代碼:
with open('./myTextFile.csv','r') as f:
    csv.register_dialect('my_delimite', delimiter='|', quoting=csv.QUOTE_ALL)
    lines = csv.reader(f, 'my_delimite')
    for line in lines:
        print(line)
# output
#['Film', 'Year', 'Actor', 'Director', 'Box Office', 'Budget', 'Bond Actor Salary']
# ['Dr. No', '1962', 'Sean Connery', 'Terence Young', '448.8', '7', '0.6']
# ['From Russia with Love', '1963', 'Sean Connery', 'Terence Young', '543.8', '12.6', '1.6']
# ['Goldfinger', '1964', 'Sean Connery', 'Guy Hamilton', '820.4', '18.6', '3.2'] 

可以發現輸出是以|隔開的,那這就是register_dialect的用法,用來變更分隔符號。

可以比較跟下面這個程式碼的差別(讀取同個檔案),可以看到輸出就沒有被分隔開來,因爲預設爲逗點(,)

with open('./myTextFile.csv','r') as f:
    lines = csv.reader(f)
    for i in lines:
        print(i)
# ['Film|Year|Actor|Director|Box Office|Budget|Bond Actor Salary']
# ['Dr. No|1962|Sean Connery|Terence Young|448.8|7|0.6']
# ['From Russia with Love|1963|Sean Connery|Terence Young|543.8|12.6|1.6']
# ['Goldfinger|1964|Sean Connery|Guy Hamilton|820.4|18.6|3.2']
  • 當然,在寫入時也可以增加參數delimiter,定義分隔的福號,像這樣:
writer = csv.writer(csvfile, delimiter=' ')
  • 列出在目前csv中的所有delimiter
print (csv.list_dialects())
  • 刪除delimiter 
unregister_dialect(name)

 

二、JSON使用

JSON (JavaScript Object Notation), specified by RFC 7159 (which obsoletes RFC 4627) and by ECMA-404, is a lightweight data interchange format inspired by JavaScript object literal syntax (although it is not a strict subset of JavaScript [1] ).

上面爲JSON的介紹,總之JSON是一種輕量級的數據交換格式也很好閱讀,就像是Python中的Dictionary一樣。

 

其實json套件,主要只有兩個函數要用,分別是:

  • json.dumps : 用來將Python的資料類型編成JSON格式。
  • json.loads : 將JSON物件轉爲Python資料類型。

範例:

  • 建立一個dictionary資料,裏面包含name, height, weight這三個Key的資料。
  • 透過dumps將這個dic轉成JSON的字串。
  • 將JSON字串轉回Python Dictionary格式。
import json

data = {
    'name' : 'plusone''',
    'height' : 155,
    'weight' : 40
}

jsonStr = json.dumps(data, sort_keys=True, indent=1)
print(jsonStr)

data = json.loads(jsonStr)
print(data)

參數:

  • sort_keys : 這個應該字面上很好理解了,是否排序Key。
  • indent : 若給非負整數,會幫你格式編排好看依照(填入的)數字等級。

可以比較兩者差異:

json_str = json.dumps(data, sort_keys=True, indent=5)
print(json_str)
# {
#      "height": 155,
#      "name": "plusone",
#      "someStr": [
#           {
#                "a": 123,
#                "b": 456
#           }
#      ]
# }

json_str = json.dumps(data, sort_keys=True, indent=1)
print(json_str)

# {
#  "height": 155,
#  "name": "plusone",
#  "someStr": [
#   {
#    "a": 123,
#    "b": 456
#   }
#  ]
# }
  • 基本上json編碼對Python而言幾乎沒有改變包含Noneboolintfloatstrlisttupledictionary
JSON Python
object dict
array list
string str
number (int) int
number (real) float
true True
false False
null None
  • 比較特別的是trueTruefalseFalse,而None則會轉爲Null,例如:
data = {
    'one':True,
    'two':False,
    'three':None
}

json_str = json.dumps(data, indent=3)
print(json_str)

# output
# {
#    "one": true,
#    "three": null,
#    "two": false
# }

接着要說明pprint()這個套件。在loads()print()出來會很難閱讀,這時候可以使用pprint()

from pprint import pprint

data = {
    'one':True,
    'two':False,
    'three':
        {
        'text':[{'something': '2343488854324'},
            {'something': '2343453454354'}, 
            {'something': '1231242343545'},
            {'something': '3423423432113'}]
        }
}
# output
# {'one': True,
#  'three': {'text': [{'something': '2343488854324'},
#                     {'something': '2343453454354'},
#                     {'something': '1231242343545'},
#                     {'something': '3423423432113'}]},
#  'two': False}

若是用print()

# {'one': True, 'two': False, 'three': {'text': [{'something': '2343488854324'}, {'something': '2343453454354'}, {'something': '1231242343545'}, {'something': '3423423432113'}]}}

參考:

json — JSON encoder and decoder — Python 3.7.1rc1 documentation
pprint — Data pretty printer — Python 3.7.1rc1 documentation

三、pickle使用

1、pickle序列化

pickle.dump()方法將obj對象序列化爲字節(bytes)寫入到file文件中:

pickle.dump(obj, file, protocol=None, *, fix_imports=True)

pickle.dumps()方法將obj對象序列化並返回一個bytes對象

pickle.dumps(obj, protocol=None, *, fix_imports=True)

例:

import pickle


dict1 = dict(name='八岐大蛇',
             age=1000,
             sex='男',
             addr='東方',
             enemy=['八神', '草薙京', '神樂千鶴'])
print(dict1)
data_dumps = pickle.dumps(dict1)
print(data_dumps)
print(type(data_dumps))  # 返回的是bytes

data_file = open('dump.txt', 'wb')
pickle.dump(dict1, data_file)
data_file.close()

# 控制檯輸出

# 控制檯輸出
{'name': '八岐大蛇', 'age': 1000, 'sex': '男', 'addr': '東方', 'enemy': ['八神', '草薙京', '神樂千鶴']}
b'\x80\x03}q\x00(X\x04\x00\x00\x00nameq\x01X\x0c\x00\x00\x00\xe5\x85\xab\xe5\xb2\x90\xe5\xa4\xa7\xe8\x9b\x87q\x02X\x03\x00\x00\x00ageq\x03M\xe8\x03X\x03\x00\x00\x00sexq\x04X\x03\x00\x00\x00\xe7\x94\xb7q\x05X\x04\x00\x00\x00addrq\x06X\x06\x00\x00\x00\xe4\xb8\x9c\xe6\x96\xb9q\x07X\x05\x00\x00\x00enemyq\x08]q\t(X\x06\x00\x00\x00\xe5\x85\xab\xe7\xa5\x9eq\nX\t\x00\x00\x00\xe8\x8d\x89\xe8\x96\x99\xe4\xba\xacq\x0bX\x0c\x00\x00\x00\xe7\xa5\x9e\xe4\xb9\x90\xe5\x8d\x83\xe9\xb9\xa4q\x0ceu.'
<class 'bytes'>

Process finished with exit code 0


2、pickle反序列化

pickle.load() 從一個對象文件中讀取序列化數據,將其反序列化之後返回一個對象:

pickle.load(file, *, fix_imports=True, encoding="ASCII", errors="strict")

pickle.loads() 將bytes反序列化並返回一個對象:

pickle.loads(bytes_object, *, fix_imports=True, encoding="ASCII", errors="strict")

例:

data_loads = pickle.loads(data_dumps)
print(data_loads)

data_file = open('dump.txt', 'rb')
data_load = pickle.load(data_file)
print(data_load)

# 反序列化輸出:

{'name': '八岐大蛇', 'age': 1000, 'sex': '男', 'addr': '東方', 'enemy': ['八神', '草薙京', '神樂千鶴']}
{'name': '八岐大蛇', 'age': 1000, 'sex': '男', 'addr': '東方', 'enemy': ['八神', '草薙京', '神樂千鶴']}

Process finished with exit code 0

3、pickle與json的區別

pickle與json都可以實現序列化以及反序列化,它們之間不同的有以下幾點:

1)pickle不是用於多種語言間的數據傳輸,它僅作爲python對象的持久化,只針對python的數據類型;而json可以支持更多語言的序列化和反序列化,在python中序列化一個自定義的類對象時,會拋出一個 TypeError。 
2)json的序列化輸出是文本對象是str類型,而pickle序列化的輸出是二進制字節-bytes。 
3)json可讀性優於pickle。
 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章