以下のget_env.pyで、env.prfを各行読み込んで処理を行っています。
env.prfに空行があると、エラーになってしまうのですが、どのようにハンドリングすべきでしょうか?
(エラー的にはi.split()[1]が空行なので”list index out of range”となっていると思うのですが、できれば前段のif分岐の#以外は〜のようはハンドリングをしたいです。)
get_env.py
# -*- coding: utf-8 -*- import os with open('./env.prf', 'r') as f: text = f.readlines() for i in text: if '#' not in i: os.environ[i.split()[1].split('=')[0]] = i.split()[1].split('=')[1] print(os.environ[i.split()[1].split('=')[0]]) else: print('not__',i)
[ec2-user@ip-10-0-0-197 ~]$ python get_env.py 'aaa' 'bbb' ('not__', '## test\n') ('not__', '#test\n') ('not__', '#\n') Traceback (most recent call last): File "get_env.py", line 9, in <module> os.environ[i.split()[1].split('=')[0]] = i.split()[1].split('=')[1] IndexError: list index out of range
["env.prf"]
export AAA='aaa' export BBB='bbb' ## test #test # # # aaaaa ########## aaaa export CCC='ccc'
readlines()で読み込んだ文字列には最後改行がついています。
例えばenv.prfの最初の行でiはこうなります
$ python
Python 2.7.17 (default, Nov 7 2019, 10:07:09)
[GCC 9.2.1 20191008] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> f=open('./env.prf', 'r')
>>> lines=f.readlines()
>>> lines
["export AAA='aaa'\n", "export BBB='bbb'\n", '## test\n', '#test\n', '#\n', '\n', '#\n', '\n', '# aaaaa\n', '########## aaaa\n', "export CCC='ccc'\n"]
>>> i=lines[0]
>>> i
"export AAA='aaa'\n"
>>>
これをsplit()すると。。。
>>> i.split()
['export', "AAA='aaa'"]
>>>
こうなります。export直後の空白と分かりにくいですが、最後の改行の2つで区切られてます。
2つの区切りで区切られたら本来3つに分割されるはずですが、引数なしのsplitは特殊で、最後の分割された文字列が空文字列だったらそれを含まない結果が返ります。
今回2つ目の区切り文字は改行だったのですが、改行の後ろは何もないので、3つ目の文字列が空文字列になり、それを含まない2つの文字列が返っています。
さて、6行目には空行があるのですが、これをsplitした場合はどうなるかというと...
>>> '\n'.split()
[]
>>>
中身が何もないリストになりました。これはどういうことかというと、、、今回区切りは改行1つのみなので、本来は2分割になります。2つ目の文字列は空文字列になるので、結果から除外されるはずですが、1つ目の文字列は出てきてもいいのでは?と思うかも知れません。しかし、末尾の空文字列が除外されるなら先頭の空文字列も要らないよね?という理由から、先頭の文字列も除外され、このケースでは要素0個のリストになっています。
つまり、
>>> \n'.split()[0]
File "<stdin>", line 1
\n'.split()[0]
^
SyntaxError: unexpected character after line continuation character
>>>
インデックスは0でもエラーになります。中身空ですからね。存在しない0番目の要素を取り出そうとしたらエラーになってしまいます。もちろん1番目の要素もないので同様にエラーです。
エラーの正確な原因が分かったところでそれをどうすべきですが、まず原則として、アプリケーションはエラーで落ちてはいけません。今回のプログラムはエラーで落ちてしまっています。選択肢としては2つ。
1.エラーになる可能性があったらそれを事前にチェックしてエラーが起きないようにする
if len('\n'.split()) >= 2:
....
2.エラーが起きてからそれを即座に補足する
try:
'\n'.split()[1]
...
except IndexError:
...
で、普通は1.を選択します。つまり、1番目の要素を取得する前に要素数が2以上であることを確認します。後は仕様として空行をどう取り扱うかの決め次第です。エラーとして処理したいなら、エラーメッセージを表示して終了するのが正しいし、無視させたいなら何もせずに次の処理でもいいと思います。
最後に、python2.7は今年の元旦からサポートが切れています。どうしても使う理由がないのなら使わない方がいいです。
回答2件
あなたの回答
tips
プレビュー