Home > Tags > Python
Python
Python: ファイル読み込み時の例外の扱い例 - try、except、else、finallyブロック
- 2008-09-18 (木)
- Python
ファイルのパスや名前のミス、パーミッションの権限が無い等が原因でファイルを読み込めない場合があります。そのような場合、すなわち例外が発生した際にそこで処理を中断して、発生した例外に合わせた処理ブロックにジャンプする構文が、try:~except Error:~構文です。
今回は、コマンドライン引数で英文テキストファイル名を指定し、スクリプト内でファイル内容を読み込み、単語数をカウントし出力するスクリプトを以って、オプションのelse、finallyブロックを含めた例外ブロックの扱いを確認します。
ただし、ここでの「単語」とは、1つの空白文字で区切られた文字列とします(簡単に)。
ソースコード
# -*- coding: UTF-8 -*-
import sys
script_name = sys.argv[0]
try:
arg = sys.argv[1]
f = open(arg, 'r')
except IndexError:
print 'Usage: %s TEXTFILE' % script_name
except IOError:
print '"%s" cannot be opened.' % arg
else:
print arg, 'contains', len(f.read().split(' ')), 'words.'
f.close()
finally:
print 'n"%s" process end.' % script_name
quit()
print 'Not reach this line.'
コードの説明
tryブロック
まず、例外を発生させる恐れのある行は、tryブロック内に書きます。
ここで発生しそうなのは、コマンドライン引数が格納されているリストへのアクセス部分であるsys.argv[1]です。[]演算子で存在しない要素を参照するエラー、もとい例外が発生する恐れがあります。
また、ファイルを開くopen(arg, 'r')も冒頭の理由で例外を発生させるかもしれません。
exceptブロック
exceptブロックは、tryブロックで例外が発生した場合にのみ実行されるブロックです。その為、例外が発生しない場合は実行されません。
発生する可能性のある例外のタイプ毎にexceptブロックを書けば、そのタイプ毎の例外への対処処理を書くことが出来ます。
except TYPE_AError:
TYPE_AErrorが発生した際のとある処理...
except TYPE_BError:
TYPE_BErrorが発生した際のとある処理...
elseブロック (オプション)
elseブロックは全てのexceptブロックの後に書きます(任意なので書かなくても構わない)。
elseブロックはtryブロックで例外が発生しなかった場合にのみ実行されるブロックです。今回は、ファイルの読み込みとクローズに使用しています。
finallyブロック (オプション)
finallyブロックはtryブロックで例外が発生するしないに関わらず実行されるブロックです(任意なので書かなくても構わない)。
実行結果
読み込むテキストファイルを以下のaLine.txtとします。
aLine.txt
Unless I set the standard where I am in any level, I'll be puzzled about what I should do from now on.
コマンドラインで適切な引数を与えた場合
$ python excp01.py aLine.txt aLine.txt contains 22 words. "excp01.py" process end.
存在しないファイル名を引数を与えた場合
$ python excp01.py texfile.tex "texfile.tex" cannot be opened. "excp01.py" process end.
コマンドライン引数を与えなかった場合
$ python excp01.py Usage: excp01.py TEXTFILE "excp01.py" process end.
例外オブジェクト名をpython処理系に聞いてみる
どんなメソッドや関数、演算子が、どのような例外を投げるのか予測が付かない場合があるかと思います。
そんな場合でもとりあえずスクリプトを実行してエラーを確認してみましょう。
SyntaxError: invalid syntax以外のエラーがある場合、例えば、
$ python excp01.py Traceback (most recent call last): File "excp01.py", line 5, inarg = sys.argv[1] IndexError: list index out of range
のような場合は、最終行の行頭のIndexErrorが例外名となります。
何でも例外任せにしていいの?
計算量からみてあまり良いとは言えません。今プログラムのコマンドライン引数の確認を、
if len(sys.argv) != 2: ホニャララ
とすると整数の比較ですみますが、例外のキャッチに任せると、例外インスタンスを生成し送出するという、結構な計算量がかかります。ネットワーク接続やファイル読み書きなどのIOでは有効ですが、それ以外では積極的に使わないほうがいいかもしれません。
ドキュメント
- Comments: 0
- Trackbacks: 0
Python: テキストファイルの行頭に行番号を追加
- 2008-09-08 (月)
- Python
コマンドラインで指定されたテキストファイルの行頭に行番号を追加し、そのデータを新たなファイルに書き出すスクリプトです。
ソースコード
#!/usr/bin/python
# coding: UTF-8
import sys
argvs = sys.argv
argc = len(argvs)
if (argc != 3):
print 'Usage: $ python %s target_file making_file' % argvs[0]
quit()
f = open(argvs[1])
lines2 = f.readlines()
f.close()
nf = open(argvs[2], 'w')
i = 1
for line in lines2:
nf.write('%3d: %s' % (i, line))
i = i + 1
nf.close()
仮にこのソースコードをfile05a.pyというファイルで保存した場合、使用する際はプロンプトに以下のように打ち込みます。
実行結果
プロンプト
> python file05a.py file05a.py file05a-l.txt
この結果、生成されたファイルが下記になります。
file05a-l.txt
1: #!/usr/bin/python
2: # coding: UTF-8
3:
4: import sys
5:
6: argvs = sys.argv
7: argc = len(argvs)
8: if (argc != 3):
9: print 'Usage: $ python %s target_file making_file' % argvs[0]
10: quit()
11: f = open(argvs[1])
12: lines2 = f.readlines()
13: f.close()
14: nf = open(argvs[2], 'w')
15: i = 1
16: for line in lines2:
17: nf.write('%3d: %s' % (i, line))
18: i = i + 1
19: nf.close()
- Comments: 0
- Trackbacks: 0
Python: テキストファイルに書き込み - write()、writelines()メソッド
- 2008-09-06 (土)
- Python
テキストファイルへの書き込み処理をFileオブジェクトの以下のメソッドを用いて書いてみます。
- write() - 文字列を引数に取り、ファイルに書き込む。
- writelines() - シーケンス型を引数に取り、ファイルに書き込む。
write() - 文字列を引数に取り、ファイルに書き込む
ソースコード
#!/usr/bin/python
# coding: UTF-8
# 書き込む文字列
str = """It is meaningless only to think my long further aims idly.
It is important to set my aims but at the same time I should confirm my present condition.
Unless I set the standard where I am in any level, I'll be puzzled about what I should do from now on."""
f = open('text.txt', 'w') # 書き込みモードで開く
f.write(str) # 引数の文字列をファイルに書き込む
f.close() # ファイルを閉じる
実行結果
text.txt
It is meaningless only to think my long further aims idly. It is important to set my aims but at the same time I should confirm my present condition. Unless I set the standard where I am in any level, I'll be puzzled about what I should do from now on.
writelines() - シーケンス型を引数に取り、ファイルに書き込む
ソースコード
#!/usr/bin/python
# coding: UTF-8
str = """It is meaningless only to think my long further aims idly.
It is important to set my aims but at the same time I should confirm my present condition.
Unless I set the standard where I am in any level, I'll be puzzled about what I should do from now on."""
strs = str.split('n') # 一行が一要素(文字列)のリスト
f = open('text.txt', 'w') # 書き込みモードで開く
f.writelines(strs) # シーケンスが引数。
f.close()
実行結果
text.txt
It is meaningless only to think my long further aims idly.It is important to set my aims but at the same time I should confirm my present condition.Unless I set the standard where I am in any level, I'll be puzzled about what I should do from now on.
書き込む際は、シーケンスの各要素の文字列を単に連結するだけです。間には改行も空白文字も含まれません。
そういえば、csv.writerオブジェクトを用いたCSVファイル書き込みにはlineterminatorオプション引数に、任意の連結文字列(言い方よくないね→行の終端文字)を代入できます。主に、環境に合わせた改行文字を代入するのに使います。→Python: CSVファイルに書き込み - csv.writerオブジェクト
リファレンス
- Comments: 0
- Trackbacks: 0
Python: 二値の交換
- 2008-08-28 (木)
- Python
ソート系のアルゴリズムを実装する際などに、配列の任意の2つの要素を交換する処理が必要な場合がありますので、以下にその手順の一例を示します。
ソースコード
# coding: UTF-8 a = [10, 20] print '%d %d' % (a[0], a[1]) a[0], a[1] = a[1], a[0] print '%d %d' % (a[0], a[1])
実行結果
10 20 20 10
何だかperlの多重代入を思い出します。
- Comments: 0
- Trackbacks: 0
Python: 指定したパスのディレクトリ中のファイル一覧を出力
- 2008-08-09 (土)
- Python
あるディレクトリから特定のファイルを検索したい場合、探索対象ディレクトリ内のファイルを全て取得する必要があります。今回は、引数にディレクトリを指すパスを指定することによって、そのディレクトリの内容を取得する関数を2つ示します。
ソースコード
# coding: Shift_JIS
import os # osモジュールのインポート
# os.listdir('パス')
# 指定したパス内の全てのファイルとディレクトリを要素とするリストを返す
files = os.listdir('C:\Python25\')
for file in files:
print file
実行結果の一例
DLLs Doc include Lib libs LICENSE.txt lxml-wininst.log NEWS.txt PIL-wininst.log pysqlite-wininst.log pysqlite2-doc python.exe pythonw.exe README.txt Removelxml.exe RemovePIL.exe Removepysqlite.exe Scripts tcl Tools w9xpopen.exe
ワイルドカードでリスティング対象を指定
globモジュールのglob()関数の引数内にワイルドカード「*」を含めることが出来ます。これによって、より手軽に目的のファイルを探索することが出来ます。
ソースコード
# coding: Shift_JIS
import glob
# パス内の全ての"指定パス+ファイル名"と"指定パス+ディレクトリ名"を要素とするリストを返す
files = glob.glob('C:\Python25\*.*') # ワイルドカードが使用可能
for file in files:
print file
os.listdir()と異なり、glob.glob()は取得したファイル文字列には先頭に探査ディレクトリ(引数)のパスが付いています。
実行結果の一例
C:Python25LICENSE.txt
C:Python25lxml-wininst.log
C:Python25NEWS.txt
C:Python25PIL-wininst.log
C:Python25pysqlite-wininst.log
C:Python25python.exe
C:Python25pythonw.exe
C:Python25README.txt
C:Python25Removelxml.exe
C:Python25RemovePIL.exe
C:Python25Removepysqlite.exe
C:Python25w9xpopen.exe
リファレンス
- Comments: 0
- Trackbacks: 0
Home > Tags > Python