3

デフォルトのopenメソッドを、例外もキャッチするラッパーでラップしたいと思います。動作するテスト例を次に示します。

truemethod = open
def fn(*args, **kwargs):
    try:
        return truemethod(*args, **kwargs)
    except (IOError, OSError):
        sys.exit('Can\'t open \'{0}\'. Error #{1[0]}: {1[1]}'.format(args[0], sys.exc_info()[1].args))

open = fn

私はそれの一般的な方法を作りたいです:

def wrap(method, exceptions = (OSError, IOError)):
    truemethod = method
    def fn(*args, **kwargs):
        try:
            return truemethod(*args, **kwargs)
        except exceptions:
            sys.exit('Can\'t open \'{0}\'. Error #{1[0]}: {1[1]}'.format(args[0], sys.exc_info()[1].args))

    method = fn

しかし、それは機能しません:

>>> wrap(open)
>>> open
<built-in function open>

どうやら、methodこれはパラメータのコピーであり、私が期待したような参照ではありません。pythonicの回避策はありますか?

4

3 に答える 3

4

コードの問題は、内部wrapでは、method = fnステートメントが単にローカル値を変更しているだけでmethod、大きい方の値を変更していないことですopen。これらの名前を自分で割り当てる必要があります。

def wrap(method, exceptions = (OSError, IOError)):
    def fn(*args, **kwargs):
        try:
            return method(*args, **kwargs)
        except exceptions:
            sys.exit('Can\'t open \'{0}\'. Error #{1[0]}: {1[1]}'.format(args[0], sys.exc_info()[1].args))

    return fn

open = wrap(open)
foo = wrap(foo)
于 2009-11-11T12:05:04.583 に答える
2

追加してみてくださいglobal open一般的なケースでは、マニュアルのこのセクションを見たいと思うかもしれません:

このモジュールは、Pythonのすべての「組み込み」識別子への直接アクセスを提供します。たとえば、は組み込み関数open()__builtin__.openのフルネームです。組み込みオブジェクトの章を参照してください。

このモジュールは通常、ほとんどのアプリケーションによって明示的にアクセスされませんが、組み込み値と同じ名前のオブジェクトを提供するモジュールで役立ちますが、その名前の組み込みも必要です。たとえば、組み込みのopen()をラップするopen()関数を実装するモジュールではこのモジュールを直接使用できます。

import __builtin__

def open(path):
    f = __builtin__.open(path, 'r')
    return UpperCaser(f)

class UpperCaser:
    '''Wrapper around a file that converts output to upper-case.'''

    def __init__(self, f):
        self._f = f

    def read(self, count=-1):
        return self._f.read(count).upper()

    # ...

CPython実装の詳細:ほとんどのモジュールには__builtins__、グローバルの一部として使用できる名前(「s」に注意)があります。の値__builtins__は通常、このモジュールまたはこのモジュールの__dict__属性の値のいずれかです。これは実装の詳細であるため、Pythonの代替実装では使用できない場合があります。

于 2009-11-11T11:58:07.727 に答える
1

関数return fnの最後に追加して、次のようにすることができます。wrap

>>> open = wrap(open)
>>> open('bhla')
Traceback (most recent call last):
  File "<pyshell#24>", line 1, in <module>
    open('bhla')
  File "<pyshell#18>", line 7, in fn
    sys.exit('Can\'t open \'{0}\'. Error #{1[0]}: {1[1]}'.format(args[0], sys.exc_info()[1].args))
SystemExit: Can't open 'bhla'. Error #2: No such file or directory
于 2009-11-11T12:04:36.800 に答える