2016-02-06 1 views
7

私は、この問題を解決するのは難しいだけでなく、より高度な方向に考えています。決定に至る前に、私はこの問題に対処するために専門家の助言を求めることを考えました。ジェネレータで例外を発生させ、Pythonの他の場所で処理します。

拡張ジェネレータには、発信者がジェネレータ(コルーチン)にメッセージを渡すことを許可する新しいメソッド.send()と.throw()があります。

pythonのドキュメントから:これは非常に便利です。特に、ジェネレータに呼び出し側で発生した例外を処理するよう要求する.throw()メソッド。

リクエスト#1:上記のステートメントのコード例。この説明のためのコードスニペットは見つかりませんでした。

しかし、私は逆問題も考慮しています:ジェネレータは例外を発生させ、呼び出し元に渡し、呼び出し元に "修復"させ、ジェネレータ自身の実行を続けることができますか?それは私が「逆スロー」と呼ぶものです。

リクエスト#2:上記のステートメントのコード例。この説明のためのコードスニペットは見つかりませんでした。

ジェネレータで例外を発生させるだけでOKではありません。私は "raise SomeException"ジェネレータで試してみましたが、動作しませんでした。なぜなら "raise"の後にジェネレータを実行できなくなったからです---単に停止し、さらにジェネレータを実行しようとするとStopIteration例外が発生します。言い換えれば、「上昇」は「歩留まり」よりもはるかに致命的です。発信者に帰属した後に再開することはできますが、「引き上げる」ことは自らを死の最後に送ります。

Pythonで「逆スロー」を行う簡単な方法があるのだろうか?これにより、互いに例外を投げて協力するコルーチンを書くことができます。なぜ例外を使用するのですか?まあ、私は知りません...それはすべて大まかなアイディアとして始まりました。

ケーススタディのCODE:

class MyException(Exception):pass 


def handleError(func): 
''' handle an error''' 
    errors =[] 
    def wrapper(arg1): 
     result = func(arg1) 

     for err in findError(result): 
      errors.append(err) 

     print errors 
     return result 

    return wrapper 

def findError(result): 
''' 
Find an error if any 
''' 
    print result 
    for k, v in result.iteritems(): 
     error_nr = v % 2 
     if error_nr ==0: 
      pass 
     elif error_nr > 0: 
      yield MyException 

@handleError 
def numGen(input): 

''' This function take the input and generates 10 random numbers. 10 random numbers are saved in result dictionary with indices. Find error decorator is called based on the result dictionary''' 

    from random import randint 
    result= {} 
    errors = [] 
    for i in range(9): 
     j = (randint(0,4)) 
     result[i] = input + j 
    return result 

if __name__ == '__main__': 
    numGen(4) 

誰もが両方のケーススタディの例をもとにアイデアが(発電機で例外を上げるし、その逆も他の場所でそれを処理)してください説明してもらえますか?私は両方の方法のプロと詐欺を期待しています。

ありがとうございます。

信用できる公式ソースからの回答を探しています。

答えて

0

要求#1(.throwための例())

私は実際にこれを使用したことがないが、あなたは事後発電機で動作を変更するためにそれを使用することができます。もちろん、.sendでもこれを行うことができますが、try-exceptブロックで集中化するのではなく、yield式(コード内のいくつかの場所にある可能性があります)の行で対処する必要があります。

def getstuff(): 
    i=0 
    try: 
     while True: 
      yield i 
      i+=1 
    except ValueError: 
     while True: 
      yield i**2 
      i+=1 

generator = getstuff() 

print("Get some numbers...") 
print(next(generator)) 
print(next(generator)) 
print(next(generator)) 

print("Oh, actually, I want squares!") 
print(generator.throw(ValueError)) 
print(next(generator)) 
print(next(generator)) 
0

リクエスト#1:上記の文の例のコード。この説明のためのコードスニペットは見つかりませんでした。上記の文のための任意のコード例:

はayscioソースコード

https://github.com/python/asyncio/search?utf8=%E2%9C%93&q=.throw

要求#2を見てみましょう。この説明のためのコードスニペットは見つかりませんでした。

はpythonでそれに* 今日方法はありません - (有用であることが証明されている場合)、多分それはあなたが他の場所で例外を発生させる枠組みを知らせるために利回りを使用することができている素敵な強化

*することができ..

0

私はこの問題を数回解決する必要があり、他の人が何をしたのかを検索した後、この問題が発生しました。私はOPの示唆した方法のいずれかを使用するとは思わないが、かなり複雑である。

リファクタリングを少し必要とする1つのオプションは、raiseではなく、単純にthrowジェネレータ(別のエラー処理ジェネレータ)の例外です。これは、常に最善の解決策になるだろうされていませんが、それは確かにオプションだ、と理解することは比較的容易

def f(handler): 
    # the handler argument fixes errors/problems separately 
    while something(): 
     try: 
      yield something_else() 
     except Exception as e: 
      handler.throw(e) 
    handler.close() 

def err_handler(): 
    # a generator for processing errors 
    while True: 
     try: 
      yield 
     except Exception1: 
      handle_exc1() 
     except Exception2: 
      handle_exc2() 
     except Exception3: 
      handle_exc3() 
     except Exception: 
      raise 

def process(): 
    handler = err_handler() 
    for item in f(handler): 
     do stuff 

:ここではそれがどのようなものであるかです。

関連する問題