ひとり勉強ログ

ITエンジニアの勉強したことメモ

14章 CSVファイルとJSONデータ【退屈なことはPythonにやらせよう】

CSVモジュール

Readerオブジェクト

CSVモジュールを使ってCSVファイルからデータを読み込むには、Readerオブジェクトを生成する。

>>> import csv # 別途インストール不要
>>> example_file = open('example.csv')
>>> example_reader = csv.reader(example_file)
>>> example_data = list(example_reader) # Readerオブジェクトをlist()に渡すと、リストが返ってくる
>>> example_data
[['4/5/2014 13:34', 'Apples', '73'], ['4/5/2014 3:41', 'Cherries', '85'], ['4/6/2014 12:46', 'Pears', '14'], ['4/8/2014 8:59', 'Oranges', '52'], ['4/10/2014 2:07', 'Apples', '152'], ['4/10/2014 18:10', 'Bananas', '23'], ['4/10/2014 2:40', 'Strawberries', '98']]
>>> example_data[0][0]
'4/5/2014 13:34'
>>> example_data[0][1]
'Apples'
>>> example_data[0][2]
'73'
>>> example_data[1][1]
'Cherries'
>>> example_data[6][1]
'Strawberries'
forループでReaderオブジェクトからデータを読み出す

巨大なCSVファイルの場合は、forループの中でReaderオブジェクトを使うほうがよい。そうすれば、ファイルを一度にメモリーに読み込むことを避けられる。

>>> import csv
>>> example_file = open('example.csv')
>>> example_reader = csv.reader(example_file)
>>> for row in example_reader:
...     print('Row #' + str(example_reader.line_num) + ' ' + str(row))
... 
Row #1 ['4/5/2014 13:34', 'Apples', '73']
Row #2 ['4/5/2014 3:41', 'Cherries', '85']
Row #3 ['4/6/2014 12:46', 'Pears', '14']
Row #4 ['4/8/2014 8:59', 'Oranges', '52']
Row #5 ['4/10/2014 2:07', 'Apples', '152']
Row #6 ['4/10/2014 18:10', 'Bananas', '23']
Row #7 ['4/10/2014 2:40', 'Strawberries', '98']
Writerオブジェクト

Writerオブジェクトを用いると、データをCSVファイルに書き込むことができる。

>>> import csv
>>> output_file = open('output.csv', 'w', newline='') # 書き込みモードでファイルを開く
>>> output_writer = csv.writer(output_file) # Writerオブジェクトを生成
>>> output_writer.writerow(['spam', 'eggs', 'bacon', 'ham']) # writerowメソッドはリストを引数にとる
21
>>> output_writer.writerow(['Hello, world!', 'eggs', 'bacon', 'ham'])
29
>>> output_writer.writerow([1, 2, 3.141592, 4])
16
>>> output_file.close()
キーワード引数delimiterとlineterminator

カンマの代わりにタブ文字でセルを区切り、1行空きにする。

>>> import csv
>>> csv_file = open('example.tsv', 'w', newline='')
>>> csv_writer = csv.writer(csv_file, delimiter='\t', lineterminator='\n\n') # セル間の文字がタブ文字、行間の文字は2つの改行文字
>>> csv_writer.writerow(['apples', 'oranges', 'grapes'])
23
>>> csv_writer.writerow(['eggs', 'bacon', 'ham'])
16
>>> csv_writer.writerow(['spam', 'spam', 'spam', 'spam', 'spam', 'spam'])
31
>>> csv_file.close()

プロジェクト:CSVファイルから見出しを削除する

#! python3

import csv, os

# 見出しを削除したCSVファイルを書き込むheaderRemovedというフォルダを作る
os.makedirs('headerRemoved', exist_ok=True)

# カレントディレクトリの全ファイルをループする
for csv_filename in os.listdir('.'):
  if not csv_filename.endswith('.csv'):
    continue # CSVファイルでなければスキップ
  print('見出し削除中 ' + csv_filename + '...')

# CSVファイルを書き込む
# 最初の行を削除するのではなく、最初の行を除いたCSVファイルの複製を作る。
# プログラムには、最初の行をループ中かどうかを追跡する手段が必要。

# CSVファイルを読み込む(最初の行をスキップする)
csv_rows = []
csv_file_obj = open(csv_filename)
reader_obj = csv.reader(csv_file_obj)
for row in reader_obj:
  if reader_obj.line_num == 1: # line_num属性を使えば、CSVファイルから現在読み込んでいる行番号がわかる
    continue
  csv_rows.append(row)
csv_file_obj.close()

# カレントディレクトリの全ファイルをループする
for csv_filename in os.listdir('.'):
  if not csv_filename.endswith('.csv'):
    continue # CSVファイルでなければスキップ
  # CSVファイルを書き出す
  csv_file_obj = open(os.path.join('headerRemoved', csv_filename), 'w', newline='')
  csv_writer = csv.writer(csv_file_obj) # WriterオブジェクトはheaderRemovedフォルダの中にReaderと同じcsv_filenameという名前のCSVファイルとしてcsv_rowsを書き込む。
  for row in csv_rows:
    csv_writer.writerow(row) # csv_rowsをループして行をファイルに書き出す
  csv_file_obj.close()

JSONAPI

loads()関数を用いてJSONを読み込む
>>> string_of_json_data = '{"name": "Zophie", "isCat": true, "miceCaught": 0, "felineIQ": null}' # JSON文字列は常にダブルクオートで囲む
>>> import json
>>> json_data_as_python_value = json.loads(string_of_json_data)
>>> json_data_as_python_value
{'name': 'Zophie', 'isCat': True, 'miceCaught': 0, 'felineIQ': None}
dumps()関数を用いてJSONを書き出す
>>> python_value = '{"name": "Zophie", "isCat": true, "miceCaught": 0, "felineIQ": null}'
>>> import json
>>> string_of_data = json.dumps(python_value)
>>> string_of_data
'"{\\"name\\": \\"Zophie\\", \\"isCat\\": true, \\"miceCaught\\": 0, \\"felineIQ\\": null}"'
天気予報データを取得する

プログラムは次の処理を行う。

  • コマンドラインから地名を読み込む。
  • OpenWeatherMap.orgからJSON形式で天気予報データをダウンロードする。
  • JSONデータ文字列をPythonのデータ構造に変換する。
  • 今日と明日、明後日の天気予報を表示する。

そのため、次のコードを実装する必要がある。

  • sys.argvの文字列を結合して地名を取得する。
  • requests.get()を呼び出して天気予報データをダウンロードする。
  • json.loads()を呼び出し、JSONデータをPythonのデータ構造に変換する。
  • 天気予報を表示する。