3
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

csvファイルを読み込んでブラウザに表示する

Posted at

概要・目標

持ち運び用のノートPCにExcelをインストールしていないのでcsvファイルが表形式で照会できない。
スプレッドシートでの代用は可能だが、スプレッドシートで表示するにはネット接続が必要で、無駄なパケット通信をしたくない。
CSVファイルの照会だけならオフラインで十分。
色々とググっているとpythonのpandasライブラリでCSVファイルの読み込みやhtmlの出力もできることがわかった。
pythonの勉強を目的としてcsvファイルを読み込んでブラウザに表示するプログラムを作成する。

環境

  • Windows10
  • python 3.8.1
  • VSCode

やること、やる順

  1. pandasをpipでインストールする
  2. pythonプログラムを作成する
  3. ブラウザで表示する

pandasをpipでインストールする

VSCodeのターミナルでお決まりのコマンド pip install pandas を実行する。
なぜかエラー発生...ソース書く前に想定外のエラーを引くキャラなんで、これぐらいのエラーが発生することはお見通し。

(1)
ERROR: Could not install packages due to an EnvironmentError: [WinError 5] アクセスが拒否されました。: 'c:\\program files\\python38\\lib\\site-packages\\pip-19.2.3.dist-info\\entry_points.txt'
Consider using the `--user` option or check the permissions.

(2)
WARNING: You are using pip version 19.2.3, however version 19.3.1 is available.
You should consider upgrading via the 'python -m pip install --upgrade pip' command.

(1)・・・アクセスが拒否されましたやpermissionsって出てるからおそらく権限なんでしょうね。
VSCodeのターミナルは諦めて、コマンドプロンプトを管理者で起動してpipコマンドを実行すると正常にインストールできた。

(2)python3.8.1でインストールされたpipのバージョンが古いので警告が出ている。
''で表示されたコマンドを実行し、pipのアップグレードを(1)の実行前に実施した。

pythonプログラムを作成する

pandasのread_csv()でCSVファイルを読み込み、to_html()でCSVデータを

に変換し、htmlに書き込む。
読み込んだCSVファイルで空白がある場合は欠損値として扱かわれNaNに変換されるため、na_filter=Falseで変換しないようにする。
htmlのタイトルにはCSVファイル名を表示する。
main.py
import os
import pandas as pd
import sys

def main():
    # 引数1からCSVファイルを取得する
    args = sys.argv
    haserror = False
    csvfile = ''

    # 引数なしはエラーとする
    if 1 == len(args):
        print("CSVファイルが指定されていません。")
        haserror = True
    else:
        csvfile = args[1]

        # ファイル名が不正の場合はエラー
        if os.path.exists(csvfile) == False:
            print("指定したファイルは存在しません。")
            haserror = True
        
        # CSVファイルではない場合はエラーとする
        if csvfile.endswith(".csv") == False:
            print("CSVファイル以外が指定されています。")
            haserror = True
        
    if haserror == True:
        return()
    else:
        print("CSVファイルをhtmlに変換します。")

    # CSVファイル読み込み
    csvdata = pd.read_csv(csvfile, na_filter=False)

    # htmlファイル読み込み
    htmldata = ''
    with open('templete.html',mode='r',encoding='utf-8') as htmlfile:
        htmldata = htmlfile.read()

    # CSVファイルをhtmlに変換
    rpdict = { "filename" : os.path.basename(csvfile), "table" : csvdata.to_html() }
    htmldata = htmldata.format(**rpdict)

    # htmlファイル出力
    with open('csvconverted.html',mode='w',encoding='utf-8') as outputhtml:
        outputhtml.write(htmldata)

if __name__== '__main__':
    main()

変換前html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title> {filename} </title>
        <link rel="stylesheet" type="text/css" href="style.css"/>
    </head>
    <body>
        <div class="csvlist">
            {table}
        </div>
    </body>
</html>

変換後html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title> test.csv </title>
        <link rel="stylesheet" type="text/css" href="style.css"/>
    </head>
    <body>
        <div class="csvlist">
            <table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>日付</th>
      <th>休日区分</th>
      <th>出勤時刻</th>
      <th>退勤時刻</th>
      <th>労働時間</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>2019/12/1</td>
      <td>法休</td>
      <td>09:00</td>
      <td>13:00</td>
      <td>04:00</td>
    </tr>
    <tr>
      <th>1</th>
      <td>2019/12/2</td>
      <td></td>
      <td>09:00</td>
      <td>21:30</td>
      <td>11:30</td>
    </tr>
    <tr>
      <th>2</th>
      <td>2019/12/3</td>
      <td></td>
      <td>09:00</td>
      <td>21:30</td>
      <td>11:30</td>
    </tr>
    <tr>
      <th>3</th>
      <td>2019/12/4</td>
      <td></td>
      <td>09:00</td>
      <td>21:00</td>
      <td>11:00</td>
    </tr>
    <tr>
      <th>4</th>
      <td>2019/12/5</td>
      <td></td>
      <td>09:00</td>
      <td>20:00</td>
      <td>10:00</td>
    </tr>
    <tr>
      <th>5</th>
      <td>2019/12/6</td>
      <td></td>
      <td>09:00</td>
      <td>20:00</td>
      <td>10:00</td>
    </tr>
    <tr>
      <th>6</th>
      <td>2019/12/7</td>
      <td>公休</td>
      <td></td>
      <td></td>
      <td></td>
    </tr>
    <tr>
      <th>7</th>
      <td>2019/12/8</td>
      <td>法休</td>
      <td></td>
      <td></td>
      <td></td>
    </tr>
  </tbody>
</table>
        </div>
    </body>
</html>

ふりかえり

  • htmlファイルに出力されたCSVファイルの内容が文字化けしていた。open()でencoding指定していなかったため、デフォルト(shift-jis)の文字コードで処理されてしまう。encoding='utf-8'を指定して文字化けしないようにした。
  • templete.htmlにてファイル名とcsv内容を出力するフィールドに対してformat()実行時にKeyErrorが発生した。当初はformat(key="")を2か所コーディングしていたが、1つずつformatすると対象文字列内から指定したkey項目に置換されるため、置換されなかったkey項目が存在してることをKeyErrorになっていた。formatの使い方は難しい・・・置換対象はkey-value形式のディクショナリ形式で宣言し、formatにはディクショナリを指定して置換すると正しく置換できた。
  • read_csv()での実行結果が2次元配列型で参照できるため、扱いやすくてびっくりした。

製作物はこちら
https://github.com/otowmoyarng/FreeStudyRepo/tree/master/20191228-pythoncsvviewer

3
6
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?