2018年2月5日月曜日

【Googleクラウド・機械学習編】日報解析バッチ作成中2~ファイル読み込み~

株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

最近は機械学習について勉強中です。
現在はGoogleの機械学習API「CLOUD NATURAL LANGUAGE API」の検証と、Pythonの勉強を並行して進行しています。

初心者の勉強として、簡単なバッチを作っていきたいと思います。


ファイル読み込み

今回はローカルPC内に置いたファイルを読み込むところまで進めたいと思います。

まず、メールをローカルPCに置きます。




「C:/MyMail/【日報】遠藤_20160201 - 'endo@genesis-net.co.jp' (endo@genesis-net.co.jp) - 2016-02-02 0650.eml」

こんなようなパスのファイルが沢山置かれました。

では、まずはファイル1コを読み込んでみましょう。

ファイル読み込み:1コ

このファイルを読み込むソースはコレです。

filePath = "C:/MyMail/【日報】遠藤_20160201 - 'endo@genesis-net.co.jp' (endo@genesis-net.co.jp) - 2016-02-02 0650.eml"
for line in open(filePath, 'r',encoding='ISO-2022-JP'):
    print(line)

この簡単さよ。

実質2行でファイルを全部開けます。

調べたところ、上記の書き方はCLOSE処理も自動的に行ってくれているようですね。
意識的にクローズしたい場合は、こちら。

filePath = "C:/MyMail/【日報】遠藤_20160201 - 'endo@genesis-net.co.jp' (endo@genesis-net.co.jp) - 2016-02-02 0650.eml"
f = open(filePath, 'r',encoding='ISO-2022-JP')

for line in f:
    print(line)

f.close()

たぶん、読み込み処理だったら上記の書き方だけで大概は解決するんじゃないかな?
ファイルを読む時って、特別な理由が無い限りは頭からお尻まで全部読み込んでしまうものですからね。

今回は登場しませんが、書き込み処理だったら自分でクローズする必要がありそうです。

ファイルを開くことよりもクローズすることを気にする辺りに、私の玄人ぶりを察して頂ければと思います。

「r」とは、読み込みモードで開くという意味です。
「書き込みモード」「追加書き込みモード」「読み書き両用モード」などいくつかあるようですね。

「読み書き両用モード」というのは、何が起きるか分からないので私はオススメ出来ませんが。
同じファイルを読み書きしたいのであれば、専用モードで毎回開きなおすのが正しいと思いますが、必要なシチュエーションもあるのかもしれませんね。

「encoding='ISO-2022-JP'」は、もちろん文字エンコーディングです。
デフォルトはUTF-8なので、何も指定しなければもちろん文字化けします。


ファイル読み込みについては以上です。
実に簡単でしたね。

ファイル読み込み:全部

次に、フォルダ内のファイル全部読み込みに行ってみましょう。

import os

dirPath = 'C:/MyMail'
files = os.listdir(dirPath)

for file in files:
    for line in open(os.path.join(dirPath,file), 'r',encoding='ISO-2022-JP'):
        print(line)

まず、以下の部分が特定フォルダ配下のファイル名の一覧を取得する処理です。

  • files = os.listdir(dirPath)

ここで一つ気になったのは、Javaで言うところの「File型」とかそういうのではなく、単にファイル名の文字列が配列でぶっこまれているだけということですね。

だから、配列をループで回して読み込む際は、以下のようにファイルを絶対パスに直さなければならないのです。
それが「join」です。

  • os.path.join(dirPath,file)

要するに「ディレクトリパス」+「/」+「ファイル名」という結合を行っているのですが、「/」の部分はOSで差があったりしますからね。
その辺をクールに処理してくれるのが「join」なのです。

では、「毎回joinしてフルパスを構築せねばならんのか?」と言いますと、それとは別にglobという書き方があります。

import glob

dirPath = 'C:/MyMail/*'
files = glob.glob(dirPath)

for file in files:
    for line in open(file, 'r',encoding='ISO-2022-JP'):
        print(line)

dirPathを正規表現で記載することで、ファイルを絶対パスで一覧取得する機能です。
どちらが良いかはお好みで良いでしょう。

いずれにせよ、取得するのは「File型」ではなく「パス文字列」という点に、私は着目します。
処理が軽量なんですね。

Pythonは処理速度が速いことが一つの売りですが、その鱗片がこういうところに垣間見えます。

ともかく、後は取得した一覧をグルーッと回していくだけです。


for file in files:
    for line in open(os.path.join(dirPath,file), 'r',encoding='ISO-2022-JP'):
        print(line)


Pythonはこのように処理の開始と終了を{}ではなくてインデントで表現するのが特徴です。
こんな書き方をする理由としては、例えばfor文一つを書くだけでも、

for(){

for()
{

と「{」が同じ行にあるか違う行にあるかどうかで宗教戦争が起きてしまうことを回避する為の作戦だそうです。
誰が書いても似たようなソースになるということを目指した結果です。

しかし、

「いくら理由があるにしたって、インデントで表現するかよ、普通?」

って思いますよね?
思ってたんですけど、実装してみると全然気になりません。

むしろ見易いとさえ思います。
目からウロコが落ちました。

可読性の高い言語だ、という実感があります。
良い言語です。

終わりに

今回は単にファイルを開くだけという簡単な内容でしたが、Pythonの入門としては上々の滑り出しだと感じています。

最初はみんな初心者ですからね。
簡単なところから慣れ親しんでいきたいと思います。

0 件のコメント:

コメントを投稿