2017-09-09 5 views
2

処理するデータが正確でない場合は、シェルプロンプトに戻り、役立つメッセージを表示してください。スクリプトが問題なくエラーメッセージが表示されなくなるまで、ユーザーはフラグを立てた問題を修正する必要があります。私はTTDでスクリプトを開発しているので、関数を書く前にpytestテストを書く。有用なメッセージでPythonのコマンドラインスクリプトを終了するPython

most heavily up-voted answer hereは、sys.exitを呼び出すか、SystemExitを呼び出すことによってスクリプトを編集することを提案しています。

機能:

パス(_non-text.pngがPNGファイルである、すなわち、UTF-8でエンコードされていない)、このテスト:

def test_istext(): 
    with pytest.raises(SystemExit): 
     istext('_non-text.png') 

がしかし、スクリプトが実行され続け、 try/exceptブロックが実行された後のステートメントが実行されます。

私はスクリプトが完全に終了するようにして、ユーザがデータを正しくデバッグできるようにしてください。スクリプトはそれが何をするかを行います(UTF-8テキストでいっぱいのディレクトリを処理するファイルではなく、PNG、JPG、PPTX ...ファイル)。

も試み:

以下もSystemExitのサブクラスである例外を発生させることにより、上記テストに合格し、それはまた、スクリプトを終了しない:

def istext(file_to_test): 
    class NotUTF8Error(SystemExit): pass 
    try: 
     open(file_to_test).read(512) 
    except UnicodeDecodeError: 
     raise NotUTF8Error('File {} must be UTF-8.'.format(file_to_test)) 

答えて

1

を上げる指定します。

+0

ええと、私はエラーメッセージがなくても、この例題を動作させることができませんでした。 –

+0

クラス 'NotUTF8Error(SystemExit):pass'を宣言した後、例外としてUnicodeDecodeError例外を除いた後、例外からraise NotUTF8Errorが' SyntaxError'を取得します。 –

+0

気にしないでください - 私はこれを動作させます。今度はPyTestが 'NameError:name 'NotUTF8Error' not defined'で失敗します。 –

0

try ... exceptブロックは、エラーをキャッチして内部的に処理するためのものです。あなたがしたいことは、エラーを再発生させることです。

def istext(file_to_test): 
try: 
    open(file_to_test).read(512) 
except UnicodeDecodeError: 
    print(('File {} must be encoded in UTF-8 (Unicode); try converting.'.format(file_to_test))) 
    raise 

これでメッセージが印刷され、自動的にエラーが再発されます。

古いエラーを再発生させるだけでなく、エラータイプを変更することもできます。

class MyException(SystemExit): 
    pass 


def istext(file_to_test): 
    try: 
     open(file_to_test).read(512) 
    except UnicodeDecodeError as exception: 
     raise MyException(f'File {file_to_test} must be encoded in UTF-8 (Unicode); try converting.') \ 
      from exception 

Iこの場合、あなたは、元のエラーメッセージを変更し、独自のメッセージを追加していません。このような場合のために、あなたはあなたがraise Exception from exception構文を使用することができます。:例えば、さらに

raise NameError('I'm the shown error message') 
+0

私の最初の本能は、の線に沿ってカスタム例外を作成することでした'クラスNotUTF8Error(SystemExit):'。だからあなたは 'UnicodeDecodeErrorを除いて:' '私は' 'NotUTF8Error(" Some message ")'を発行することを提案していますか? –

+0

正確に。あるいは、エラークラスの定義ですでにテキストが何を言いたいのかを指定して、再発生が必要ないようにします。 – Sudix

+0

私は2番目の提案(上記の修正された質問を参照)を試みましたが、私の元の試みのように、それはpytestを渡しますが、スクリプトを終了しません。最初の提案(メッセージの出力後に 'UnicodeDecodeError'を再発生させる)は修正されたpytestを渡しますが、スクリプトを終了することはありません。 –

0

問題はプログラムを終了する方法ではありません(sys.exit()は問題ありません)。あなたの問題は、あなたのテストシナリオがUnicodeDecodeErrorを上げていないということです。

例を簡略化して示します。

import pytest 
import sys 

def foo(n): 
    try: 
     1/n 
    except ZeroDivisionError as e: 
     sys.exit('blah') 

def test_foo(): 
    # Assertion passes. 
    with pytest.raises(SystemExit): 
     foo(0) 
    # Assertion fails: "DID NOT RAISE <type 'exceptions.SystemExit'>" 
    with pytest.raises(SystemExit): 
     foo(9) 

詳細については、コードに診断印刷を追加してください。例:最後に

def istext(file_to_test): 
    try: 
     content = open(file_to_test).read(512) 
     # If you see this, no error occurred. Maybe your source 
     # file needs different content to trigger UnicodeDecodeError. 
     print('CONTENT len()', len(content)) 
    except UnicodeDecodeError: 
     sys.exit('blah') 
    except Exception as e: 
     # Maybe some other type of error should also be handled? 
     ... 
+0

これは、pytestが '1/0'が' ZeroDivisionError'を呼び出すかどうかをテストするのではなく、 'sys.exit'が' SystemExit'を呼び出すかどうかを調べるのに役立ちます。ありがとう! –

0

、どのような仕事をすることは@ADRは1つの違いで、提案されたものと同様である:私は(f'File {file_to_test} must...')上記のようにフォーマット文字列の構文が正しく動作するために取得することができませんでした、また私ができました文字列の接頭辞fのドキュメントを参照してください。

は私のわずかに少ないエレガントな解決策は、それから、(名前を変更)機能のために:

def is_utf8(file): 
    class NotUTF8Error(SystemExit): pass 
    try: 
     open(file).read(512) 
    except UnicodeDecodeError as e: 
     raise NotUTF8Error('File {} not UTF-8: convert or delete, then retry.'.format(file)) from e 

はpytestを渡します

def test_is_utf81(): 
    with pytest.raises(SystemExit): 
     is_utf8('/Users/tbaker/github/tombaker/mklists/mklists/_non-text.png') 
+0

あなたは真剣ですか? Python 3.6のシンプルな機能を1つ使用しているので、私の解決策がもう嫌いですか? https://docs.python.org/3/whatsnew/3.6.html https://www.python.org/dev/peps/pep-0498/ – ADR

+0

@ADR参考にしていただきありがとうございます - 私の申し立て - 私が探していたその機能は見つけられませんでした。私はPython 3.5.2を持っているので、私のためにはうまくいきませんでした。私は受け入れを取り除き、あなたの答えを受け入れています! –

関連する問題