ファイルのコピー・移動・名前変更

ファイル操作関連のshutils, os, globパッケージ

ファイルのコピー

ファイルのコピーには、shutilsパッケージ、copy()またはcopy2()関数を使う。ファイルのプロパティをできるだけ残してコピーするには、copy2()関数の方が良い。

import shutils
histFolder = "履歴"
fname = "a_file.txt"
shutils.copy2(fname, histFolsder+"\\"+fname)

ファイルの移動

ファイルの移動には、shutilsパッケージ、move()関数を使う。

import shutils
histFolder = "履歴"
fname = "a_file.txt"
shutils.move(fname, histFolsder+"\\"+fname)

ファイル名の変更

ファイル名の変更には、osパッケージ、rename関数を使う。

import os
filename="a.txt"
newFName="b.txt"
os.rename(filename, newFName)

ファイルのリストの取得

ディレクトリ内のファイルのリストを取得するには、globパッケージ、glob()関数をつかう。

import glob
files = glob.glob(baseFolder+"\\*.xls")

結果はパス付のリストで得られるので、操作の時には注意。

日付や曜日の取得(datetime)

datetimeパッケージの利用例

時間や日付に関しての情報を扱うdatetimeパッケージを使って、例えば次の月曜日の日付を得る、という例。

今日の日付を得る

datetime.dateオブジェクトのtoday()関数を使う。

aDate = datetime.date.today()
print(aDate)
>>> 2017-05-28

任意のフォーマットで日付を得たい場合はdate.strftime()関数をつかう。書式の意味は、pythonのドキュメント参照。

print(aDate.strftime("%Y.%m.%d"))
>>> 2017.05.28

曜日の取得

曜日の取得には、date.weekday()関数を使う。月曜日を0、日曜日を6として0から6までの数字で返る。

print(aDate.weekday())
>>> 6 #(日曜日)

日付の演算

3日後の日付を得たいとかの時、例えば月またぎや年またぎになるときに年・月の計算までdatetimeパッケージにやってもらうには、aDate+=3ではだめで、timedeltaオブジェクトという時間の差分情報を扱うオブジェクトを使う。私がやりたかったのは今日を含めて直近の水曜日の日付を得たい事だったので、次の水曜日までの日数を表す配列を作って、日付を求める。

aDate = datetime.date.today()
print(aDate.strftime("%Y.%m.%d"))
>>> 2017.05.28
#今日は何曜日?( 月曜日 = 0, 日曜日 = 6 )
weekday = aDate.weekday()

#次の水曜日までの日数を配列にしておく。先頭が月曜日からの日数を示す。(水曜日まで、あと2日という意味)
arToWednesday=[2,1,0,6,5,4,3]

#今日からの日数は?
shiftNum = arToWednesday[weekday]
#shiftNum日分のdatetime.timedeltaオブジェクトを生成して、今日を示すaDate変数に足し込む
delta = datetime.timedelta(days=shiftNum) #時の差分を示すときはhours=, 週の場合 weeks=で指定。
nextDate = aDate + delta
print(nextDate.strftime("%Y.%m.%d"))
>>> 2017.05.31

ちなみに、特定の曜日までの日数を配列ではなく、アルゴリズムで計算するとすると、以下のような感じ。

shiftNum = 3 - aDate.weekday() 
#3は目標とする曜日で水曜日の意味。
shiftNum = shiftNum+7 if shiftNum < 0 else shiftNum
#引いて負になる場合、次の週になるので、7を足す。

WordPress のカスタマイズ

Twentysixteenでコードを公開するためのカスタマイズにチャレンジする

WordPressは結構あちこちで使われているのでpython のコード類を公開するのも簡単かと思ったのですが、いざ使ってみると全然簡単でなくいろいろ調べないといけなかったし、そもそもWordpressの使い方が今ひとつ分からず苦労したのでそういった部分をのっけています。

子テーマを作る

テーマをカスタマイズするときは、ダッシュボードから直接テーマ(例えばTwentysixteenをいじるのではなく、そのテーマの子テーマを作ってそれをカスタマイズした方が良いようです。

理由は、本体テーマがアップデートされたときに、いじった設定がリセットされてしまうことがあるようです。こちらの記事を参考に子テーマ作成を実施しています。

  1. wp-content/themes/ に子テーマ用の新しいフォルダ(ディレクトリ)を作る
  2. 上記ディレクトリの下に、style.css,functions.php の2つのファイルを置く
  3. WPのダッシュボードからその子テーマを選択する。また、各種設定を行う。

style.cssとfunctions.phpについては上記リンク先を参考に下記の様にまず設定しています。詳しくはリンク先をご覧ください。

この後は、行間などの設定を変えていこうと思いますが随時更新していきます。

Thunderbirdに届いたメールを処理する

Thunderbirdで受け取ったメールは mbox 形式という標準的なファイル形式で保存されていて、pythonの基本ライブラリだけでメールの内容を読み取って処理することが出来ます。その基本的な手順を記します。

Thudirbirdのプロファイルフォルダの確認

まず、Thundirbirdのメールのファイルがどこに保存されているのかを調べます。Windows系だと次のフォルダ以下に保存されています。

%APPDATA%\Thunderbird\Profiles\

(%APPDATA%はWindowsのユーザ名毎の環境変数)このフォルダの下に通常は、”ランダム文字列.default”というフォルダが有ります。さらに、その下に
Mail\"メールサーバ名”\"Thunderbird上のフォルダ名"
という名前のファイルが有り、それがメールメッセージを収めたmbox形式のファイルです。「受信フォルダ」の場合ファイル名は”Inbox”になります。拡張子がある”フォルダ名.msf”というファイルも有りますが、これはおそらく各mboxへのインデックスファイルで、メール本体ではありません。Thunderbird内でサブフォルダがある場合は、*.sbd という拡張子がついた名前のサブフォルダがあり、メールデータは
Mail\"メールサーバ名”\"Thunderbird上のフォルダ名".sbd\"サブフォフォルダ名"
というパスのファイルになります。

メールデータ読み出し手順

 ざっくりというと

  1. mailboxパッケージを使ってmboxファイルをオープン
  2. mbox内から取り出したいメッセージを探す
  3. メッセージのヘッダやメッセージ本体を取り出す
  4. 取り出したヘッダやメッセージをデコードし、内容に応じて所望の処理をする。

となります。以下順を追って説明します。ここでは、簡単のために受信フォルダ(Inbox)のメールを処理してみます。

mboxファイルをオープンする。

mailboxパッケージのmbox関数を受信フォルダのmboxファイルを指定して実行し、Mailboxクラスオブジェクトを得ます。

import mailbox
mail_box = mailbox.mbox("プロファイルフォルダ名/Mail/メールサーバ名/Inbox")

各メッセージ毎にループする

Mailboxクラスのkeys()関数を呼び出してメッセージのキーのリストを受け取り、ループ。

for key in mail_box.keys():

キーを使って、ヘッダやメッセージにアクセス

a_msg = mail_box.get(key)

mboxの各メールの先頭にあるFrom文字列を取り出す

from_str = a_msg.get_from()

From行文字列とは、”- %a %b %d %H:%M:%S %Y”形式の文字列。メールの送信元を表す文字列ではない。この文字列でメーラがメールを取り込んだ時間が分かる。

メッセージのヘッダをデコードする

SubjectヘッダのMIME文字列をデコードする時には、email.header::decode_header関数をつかう。このとき、各メールヘッダの情報はリストで返る。おそらく複数行になった場合に複数要素のリストとして返ってくる。

from email.header import decode_header
for bstr,enc in decode_header(a_msg['Subject']) :
if enc == None:
  usbj += bstr.decode("ascii", "ignore")
else:
  usbj += bstr.decode(enc, "ignore")
 

メッセージの本文をデコードする

電子メールのデータは、メール本文や添付ファイルなど複数のメディアで構成されていて、それが各メディア毎にMIME方式でエンコードされています。メール本文を処理したいなら異本文部分だけを取り出し、デコードしなくてはなりません。具体的には、マルチパート形式のメッセージの中からtextパートを探し、get_content_charset関数でそのパートの文字エンコードを確認してpython文字列の標準エンコードのunicodeにデコードします。少し苦労したのは、メール自身がshift_jisだと宣言するメッセージは、get_content_charset関数では文字エンコードを確認出来無いことが有り、そのフォローを入れたのとその際、メール本文には正式なshift_jisだけでなくMS拡張の文字が含まれることが有るので強制的にcp932としてデコードしないと、知らない文字がある!とpython がエラーとすることがあります。

for aa_msg in a_msg.walk():
  if not 'text' in aa_msg.get_content_type():
   continue #"text"パートでなかったら次のパートへ
  if aa_msg.get_content_charset() :
    a_text = aa_msg.get_payload(decode=True).decode(aa_msg.get_content_charset(), "ignore")
  else:
   if "charset=shift_jis" in str(aa_msg.get_payload(decode=True)):
    #ひとまず シフトJISだけ特別対応。
    a_text = aa_msg.get_payload(decode=True).decode("cp932", "ignore")
   else:
    print ("** Cannot decode.Cannot specify charset ***"+msg.get("From"))
    continue

終わりに

電子メールのデータはいろんなパターンがあって、結構苦労しました。でも、メールボックスファイルのフォーマットや、デコードなどの手続きのほとんどをpythonの標準ライブラリがやってくれたので非常に楽しく作業できました。上記のコードをつなげて、Inboxにあるメッセージを順番に読み取りFrom文字列、サブジェクト、メール本文テキスト部を主力するコードを下記に載っけておきます。