バリケンのPython日記 RSSフィード

2010-01-28

[] mbox2eml.py  mbox2eml.py - バリケンのPython日記 を含むブックマーク はてなブックマーク -  mbox2eml.py - バリケンのPython日記  mbox2eml.py - バリケンのPython日記 のブックマークコメント

ずいぶん前にRubyで作った「mbox2eml.rb」をPythonで書き直してみたよ。

このスクリプトは、mbox形式のメールファイルをemlファイルに切り出すよ。

ちなみに、mbox形式はThunderbirdとかで使われているよ。emlファイルはWindowsOutlook Expressとかで利用できるよ。

以前Rubyで書いたときは「From_エスケープ」を実装していなかったけど、今回はちゃんと実装したよ。

import sys
import re

from_line = re.compile('From\s')
blank_line = re.compile('$')
escaped_from_line = re.compile('^>(>*From )')

count = 0
blank_line_flag = True
output_file = None

for line in sys.stdin:
  if blank_line_flag and from_line.match(line):
    if output_file: output_file.close()
    count += 1
    output_file = open(str(count).zfill(4) + '.eml', 'w')
    continue
  output_file.write(escaped_from_line.sub(r'\1', line, 1))
  blank_line_flag = blank_line.match(line)

output_file.close()

これをテキストエディタで「mbox2eml.py」という名前で保存してね。

使い方

コマンドプロンプトで、

$ python mbox2eml.py < [mbox形式のメールファイル]

とすることで、「0001.eml」「0002.eml」‥‥というファイルに切り出していくよ。

トラックバック - http://python.g.hatena.ne.jp/muscovyduck/20100128

2009-02-11

[] あるディレクトリ以下のjpgファイルすべてを出力する  あるディレクトリ以下のjpgファイルすべてを出力する - バリケンのPython日記 を含むブックマーク はてなブックマーク -  あるディレクトリ以下のjpgファイルすべてを出力する - バリケンのPython日記  あるディレクトリ以下のjpgファイルすべてを出力する - バリケンのPython日記 のブックマークコメント

あるディレクトリ以下にある、すべてのjpgファイルに対して何かを操作したい、というときがあるよね。たとえばEドライブの中にあるjpgファイルをすべて出力するには、次のようにすればいいみたい。

import os
import glob

for root, dirs, files in os.walk("E:\\"):
  for fname in glob.glob(os.path.join(root, "*.jpg")):
    print fname

[] EXIF.py  EXIF.py - バリケンのPython日記 を含むブックマーク はてなブックマーク -  EXIF.py - バリケンのPython日記  EXIF.py - バリケンのPython日記 のブックマークコメント

デジタルカメラで撮影したjpgファイルには、EXIFというさまざまな情報が含まれているみたいだよ。その情報にアクセスするためには、EXIF.pyというライブラリを使えばいいみたい。

使い方はまた今度。

[] 写真の整理  写真の整理 - バリケンのPython日記 を含むブックマーク はてなブックマーク -  写真の整理 - バリケンのPython日記  写真の整理 - バリケンのPython日記 のブックマークコメント

じゃあ、EXIFライブラリを使って、デジタルカメラで撮影した写真を日付ごとのフォルダに分けてコピーするスクリプトを書いてみるよ。デジタルカメラメモリーカードがEドライブ、自分の画像フォルダがD:\Users\muscovyduck\Picturesだとすると、次のようになるよ。

# -*- coding: utf-8 -*-

import os
import glob
import shutil
import EXIF

src_dir = "E:\\DCIM"
dest_dir = "D:\\Users\\muscovyduck\\Pictures"

if os.path.exists(dest_dir) == False:
  os.mkdir(dest_dir)

for root, dirs, files in os.walk(src_dir):
  for fname in glob.glob(os.path.join(root, "*.jpg")):
    date = str(EXIF.process_file(open(fname, 'rb'))['Image DateTime'])
    year, month, day = date[:4], date[5:7], date[8:10]
    year_dir = os.path.join(dest_dir, year + u"")
    if os.path.exists(year_dir) == False:
      os.mkdir(year_dir)
    month_dir = os.path.join(year_dir, year + u"" + month + u"")
    if os.path.exists(month_dir) == False:
      os.mkdir(month_dir)
    day_dir = os.path.join(month_dir, year + month + day)
    if os.path.exists(day_dir) == False:
      os.mkdir(day_dir)
    dest = os.path.join(day_dir, os.path.basename(fname))
    if os.path.exists(dest) == False:
      shutil.copy2(fname, dest)

こうすると、たとえば2009年2月11日に撮影した写真は「2009年」フォルダの中の「2009年02月」フォルダの中の「20090211」フォルダの中にまとめてコピーされるよ。

JunJun_MathJunJun_Math2011/04/11 02:01バリケンさん、こちらのプログラム面白いとおもい、EXIF取ってきて使ってみたのですがエラーが出ました。下記のような感じです。どうかこちらのプログラム走らせてみたいのですがなぜだか教えてはいただけませんか?



Traceback (most recent call last):
File "C:\Python26\Lib\site-packages\xy\pics.py", line 16, in <module>
date = str(EXIF.process_file(open(fname, 'rb'))['Image DateTime'])
File "C:\Python26\Lib\site-packages\xy\EXIF.py", line 1688, in process_file
hdr.decode_maker_note()
File "C:\Python26\Lib\site-packages\xy\EXIF.py", line 1544, in decode_maker_note
dict=MAKERNOTE_CASIO_TAGS)
File "C:\Python26\Lib\site-packages\xy\EXIF.py", line 1353, in dump_IFD
values = self.file.read(count)
MemoryError

JunJun_MathJunJun_Math2011/04/12 12:48すみません。いくつか写真取り込まれています。途中でなんかしらの問題が起来ているようです。理由がわかりましたら教えてはいただけませんでしょうか?

ちなみにバージョンは2.6です。

muscovyduckmuscovyduck2011/04/13 14:46JunJun_Mathさん>
'Image DateTime'を'EXIF DateTimeOriginal'に変えてみると、どうでしょうか。

JunJun_MathJunJun_Math2011/04/18 12:56'Image DateTime'を'EXIF DateTimeOriginal'に変えてみると、下記のようなエラーが出ました。ただまたいくつか写真が読み込まれていました。

カシオのデジカメで撮ったのですが何か関係ありますかね???

Traceback (most recent call last):
File "C:\Python26\Lib\site-packages\xy\pics.py", line 16, in <module>
date = str(EXIF.process_file(open(fname, 'rb'))['EXIF DateTimeOriginal'])
File "C:\Python26\Lib\site-packages\xy\EXIF.py", line 1688, in process_file
hdr.decode_maker_note()
File "C:\Python26\Lib\site-packages\xy\EXIF.py", line 1544, in decode_maker_note
dict=MAKERNOTE_CASIO_TAGS)
File "C:\Python26\Lib\site-packages\xy\EXIF.py", line 1353, in dump_IFD
values = self.file.read(count)
MemoryError

トラックバック - http://python.g.hatena.ne.jp/muscovyduck/20090211

2008-12-21

[] feedparser  feedparser - バリケンのPython日記 を含むブックマーク はてなブックマーク -  feedparser - バリケンのPython日記  feedparser - バリケンのPython日記 のブックマークコメント

PythonRSSパースするにはfeedparserというライブラリを使うと楽みたい。

feedparserのインストールダウンロードサイトのfeedparser-4.1.zipダウンロードして展開して、展開したディレクトリコマンドラインで「python setup.py install」とすればいいみたいだよ。

ためしに「はてなブックマーク」のホットエントリのRSSパースしてテキストとして出力するスクリプトを書いてみたよ。

import sys
import codecs
import re
import feedparser

sys.stdout = codecs.getwriter('shift_jis')(sys.stdout)

def wrap(text, width):
  count, str = 0, ''
  result = []
  regexp = re.compile(r'^[\x20-\x7E]+$')
  for c in text:
    if regexp.findall(c):
      str += c
      count += 1
    else:
      if count + 2 > width:
        result.append(str)
        count, str = 0, ''
      str += c
      count += 2
    if count >= width:
      result.append(str)
      count, str = 0, ''
  if str != '': result.append(str)
  return result

f = feedparser.parse("http://b.hatena.ne.jp/hotentry.rss")

for e in f['entries']:
  for l in wrap(e.title, 72): print l
  print e.link
  print e.updated.replace('T', ' ')
  print
  for l in wrap(e.description, 72): print l
  print
  print

実行結果だよ。

C:\Python26>python test.py
Twitter名言
http://twittermeigen.tumblr.com/
2008-12-20 02:25:00+09:00



簿記2,3級を独学で同時に3週間で受かる方法
http://anond.hatelabo.jp/20081220025833
2008-12-20 03:03:56+09:00

http://d.hatena.ne.jp/Hash/20081219/1229690768というエントリが盛況らしく
、実際に非常に分かりやすく書かれていており、すばらしいと思う。ただ、問題
分析に重点が置かれていると思い、シンプルにこれだけやれば受かりますよとい
う間口として分かりやすさが必要と思い、別のものを書かせてもらった。日商簿
記検定2,3級のために勉強する意味会社で取らされるから、あるいは会...


独学で効率よく簿記三&二級に合格するための僕の方法 - ミームの死骸を待ち
ながら
http://d.hatena.ne.jp/Hash/20081219/1229690768
2008-12-19 22:02:45+09:00

Finance, LifeHacks 今から三年前、学部二・三年の頃の僕はテコンドーの道場
に週四回通ったり、株式投資で一攫千金を狙ってン十万塩漬けやらかしたり、一
ヶ月に三十冊くらい本を読みまくったり、合気道部時代の友人と旅行に行ったり
、学部卒で就職する気が無いくせにインターンに参加してプログラム組んでみた
りと好きなように生きていたのだけど*1、今思い返してもやっててよかったなー
と思うのが会計の勉強...


コミュニケーション能力という幻想 - ハックルベリーに会いに行く
http://d.hatena.ne.jp/aureliano/20081221/1229832078
2008-12-21 14:23:52+09:00

増田にこんな記事があった。新卒時の面接でさえなかなか通らない位コミュニケ
ーション能力に欠けている。(中略)コミュニケーション能力がない人間は職も
ないとじわじわ選択を迫るのならいっそのこと殺してほしい。30歳で死のうと思
っている ここで増田は「コミュニケーション能力」などと言っているが、しか
しそれは幻想だ。コミュニケーションは「能力」ではない。「意志」である。ア
メリカという国そのものの礎を築いたベン...


(以下省略)
トラックバック - http://python.g.hatena.ne.jp/muscovyduck/20081221

2008-12-17

[] イテレータとジェネレータ(5)  イテレータとジェネレータ(5) - バリケンのPython日記 を含むブックマーク はてなブックマーク -  イテレータとジェネレータ(5) - バリケンのPython日記  イテレータとジェネレータ(5) - バリケンのPython日記 のブックマークコメント

この間の続きだよ。

前回の例で、

  • 関数定義中にひとつでもyield文を書くと、その関数はジェネレータ関数になる
  • ジェネレータ関数を評価するとジェネレータが返る
  • そのジェネレータに対してnext()メソッドを実行すると関数の実行が始まり、yield文のところで関数の呼び出し元に返る

ということがわかったよ。

前回の例ではyield文のあとに何も書いていなかったけど、yield文に続いて式を記述しておくと、next()メソッドの呼び出し元にその評価結果を返すことが出来るよ。というか、ジェネレータは元々「値の生成器」だから値を返すのは当然だよね。

じゃあ、値が返るジェネレータの例だよ。next()メソッドを呼ぶたびにyield文が逐次実行されていき、戻り値が適宜返ってきていることが分かるよ。

>>> def fire():
	yield 3
	yield 2
	yield 1
	yield 'Fire!'

	
>>> g = fire()
>>> g.next()
3
>>> g.next()
2
>>> g.next()
1
>>> g.next()
'Fire!'
>>> g.next()

Traceback (most recent call last):
  File "<pyshell#11>", line 1, in <module>
    g.next()
StopIteration
>>> 

こんな感じでyield文をいくつも書くのは大変だから、通常のジェネレータ関数の場合はループの中にyield文を書くよ。たとえばフィボナッチ数列を生成するジェネレータ関数は次のようになるよ。

>>> def fibo(n):
	i, j = 0, 1
	for x in range(n):
		yield i
		i, j = j, i + j


>>> g = fibo(10)
>>> g.next()
0
>>> g.next()
1
>>> g.next()
1
>>> g.next()
2
>>> g.next()
3
>>> g.next()
5
>>> g.next()
8
>>> g.next()
13
>>> g.next()
21
>>> g.next()
34
>>> g.next()

Traceback (most recent call last):
  File "<pyshell#93>", line 1, in <module>
    g.next()
StopIteration
>>> 

ついでに、みんな大好きFizzBuzz問題をジェネレータを使って解いてみるよ。

>>> def fizzbuzz(n):
	for i in range(1, n + 1):
		if i % 15 == 0:
			yield "FizzBuzz"
		elif i % 5 == 0:
			yield "Buzz"
		elif i % 3 == 0:
			yield "Fizz"
		else:
			yield i

			
>>> for x in fizzbuzz(100):
	print x
(実行結果省略)
トラックバック - http://python.g.hatena.ne.jp/muscovyduck/20081217

2008-12-12

[] イテレータとジェネレータ(4)  イテレータとジェネレータ(4) - バリケンのPython日記 を含むブックマーク はてなブックマーク -  イテレータとジェネレータ(4) - バリケンのPython日記  イテレータとジェネレータ(4) - バリケンのPython日記 のブックマークコメント

この間の続きだよ。

じゃあ、前回の予告どおり今回はジェネレータを作ってみよう!ジェネレータの作り方は、ジェネレータ式を使う方法とyield文を使う方法とがあるよ。

ジェネレータ式

ジェネレータ式は簡単で、リスト内包表記の角カッコを丸カッコに変えると、結果のリストではなく結果を一つずつ返すジェネレータを生成することができるよ。

>>> [x ** 3 for x in range(0, 5)]
[0, 1, 8, 27, 64]
>>> (x ** 3 for x in range(0, 5))
<generator object at 0x00DBF9E0>
>>> g = (x ** 3 for x in range(0, 5))
>>> g.next()
0
>>> g.next()
1
>>> g.next()
8
>>> g.next()
27
>>> g.next()
64
>>> g.next()

Traceback (most recent call last):
  File "<pyshell#8>", line 1, in <module>
    g.next()
StopIteration
>>> 

yield文

次はyield文を使う方法だよ。関数定義中にyield文をひとつでも書くと、その関数は「ジェネレータ関数」という特殊な関数となるよ。次の例は極端な例だけど、

>>> def hoge():
	yield

	
>>> hoge()
<generator object at 0x00DC4F58>
>>>

という感じで、関数の評価結果としてジェネレータオブジェクトが返ってくることが分かるよ。

ジェネレータ関数によって生成されたジェネレータオブジェクトに対してnext()メソッドを呼ぶと、ジェネレータ関数の実行が始まるよ。そして yield文のところで関数の実行が停止して、呼び出し元に返るよ。ジェネレータはどこまで実行したかを覚えていて、再度next()メソッドを呼ぶと、次はそこから実行が再開されるよ。

これまたちょっと無理やりな例だけど、次のようにすればprint文を逐次実行することができるよ。

>>> def hoge():
	print 'aaa'
	yield
	print 'bbb'
	yield
	print 'ccc'
	yield

	
>>> g = hoge()
>>> g.next()
aaa
>>> g.next()
bbb
>>> g.next()
ccc
>>> 
トラックバック - http://python.g.hatena.ne.jp/muscovyduck/20081212