2017-05-17 5 views
0

私は奇妙な問題があります。最初にプログラムを実行するときに呼び出されなくても、実行中のように見えるデコレータがあります。コードに何も表示されていないのに、デコレータが実行されています

このプログラムでは何も実行されません。これを確実にするために、私はスペースで始まるすべての行を削除するためにはgrepを行なったし、得た:

[[email protected] ]$ grep -v '^\s' remedy.py 
""" 
Module to handle remedy calls 
""" 
import random 
import json 
from itertools import count 
from pprint import pprint 
import requests 
from requests.packages.urllib3.exceptions import InsecureRequestWarning 
from textproc import remuser, rempass, remurl, templateid 
def counter(): 
def logout(key): 
def remedy_api_call(func, c=None): 
def remedy_auth(): 
@remedy_api_call 
def get_entries(key, table): 
@remedy_api_call 
def get_ticket(key, table, t): 
@remedy_api_call 
def wtf_is_this_table(key, table): 
@remedy_api_call 
def new_ticket(key, person, message, bigmessage): 
@remedy_api_call 
def new_incident(key, message): 
@remedy_api_call 
def update_change(key, changeno, message): 
def update_change_undec(key, changeno, message): 
@remedy_api_call 
def new_change(key, message="", **kwargs): 
def parse_tickets(vals): 
def get_change_templates(): 
def get_incident_templates(): 

あなたが見ることができるように、いくつかの輸入は、その後、基本的に定義し、私のデコレータ機能します。

非標準モジュールインポートが1つあります。私はこれを削除し、問題が引き続き発生(基本的に、彼らはとにかくただの資格情報だ

は、ここに私のデコレータと関連する関数です:。

def counter(): 
    """ 
    wraps an itertools count instance 
    """ 
    return lambda c=count(): next(c) 

def logout(key): 
    """ 
    End api session and release key 
    """ 
    requests.packages.urllib3.disable_warnings(InsecureRequestWarning) 
    r = requests.post(url="https://" +remurl + "/api/jwt/logout", 
         headers={ "Authorization" : "AR-JWT " + key}, 
         verify=False) 
    return r.text 

def remedy_api_call(func, c=None): 
    """ 
    Decorator for handling auth for remedy API calls. 
    """ 
    try: 
     key = remedy_auth() 
    except: 
     key = "<br>" 
    if "<br>" not in str(key): 
     def wrapper(*args, **kwargs): 
      """ 
      wrapped function runs here. 
      In any wrapped function add "key" before your args 
      """ 
      r = func(key, *args, **kwargs) 
      logout(key) 
      return r 
    else: 
     print "problem getting token, retrying" 
     if c is None: 
      c = counter() 
     if int(c()) < 9: 
      remedy_api_call(func, c) 
     else: 
      print "tried too many times... Fail." 
    return wrapper 

def remedy_auth(): 
    """ 
    Get the key, get the secret 
    """ 
    try: 
     requests.packages.urllib3.disable_warnings(InsecureRequestWarning) 
     r = requests.post(url="https://" +remurl + "/api/jwt/login", 
          data={"username" : remuser, 
           "password" : rempass}, 
          verify=False) 
     return r.text 
    except: 
     return "<br>" 

そして、ここでは、私はこのコード...ベアを実行する場合、私は何を得るのです私が言うように、何も実際には、ここでのコードで呼ばされていない、気にそれはそのうちのいくつかが飾られ、機能の空白のコレクションだと、まだ私が取得:この特定の実行は、カスタムモジュールの輸入で行った

>python remedy.py 
problem getting token, retrying 
problem getting token, retrying 
problem getting token, retrying 
problem getting token, retrying 
problem getting token, retrying 
problem getting token, retrying 
problem getting token, retrying 
problem getting token, retrying 
problem getting token, retrying 
problem getting token, retrying 
tried too many times... Fail. 
Traceback (most recent call last): 
    File "remedy.py", line 75, in <module> 
    @remedy_api_call 
    File "remedy.py", line 53, in remedy_api_call 
    remedy_api_call(func, c) 
    File "remedy.py", line 53, in remedy_api_call 
    remedy_api_call(func, c) 
    File "remedy.py", line 53, in remedy_api_call 
    remedy_api_call(func, c) 
    File "remedy.py", line 53, in remedy_api_call 
    remedy_api_call(func, c) 
    File "remedy.py", line 53, in remedy_api_call 
    remedy_api_call(func, c) 
    File "remedy.py", line 53, in remedy_api_call 
    remedy_api_call(func, c) 
    File "remedy.py", line 53, in remedy_api_call 
    remedy_api_call(func, c) 
    File "remedy.py", line 53, in remedy_api_call 
    remedy_api_call(func, c) 
    File "remedy.py", line 53, in remedy_api_call 
    remedy_api_call(func, c) 
    File "remedy.py", line 56, in remedy_api_call 
    return wrapper 
UnboundLocalError: local variable 'wrapper' referenced before assignment 

from textproc...行)がハッシュアウトします。

これは正常な動作ですか?私は以前それを見たことがない。関数を含むファイルだけが完全にクリーンに動作することを期待しています。

答えて

2

デコレータは、関数が呼び出されたときではなく、関数定義の直後に実行されます。単純な例を考えてみましょう:

def foo(f): 
    print("Decorator foo is executing") 
    return f 

@foo 
def bar(): 
    pass 

結果:

Decorator foo is executing 

印刷がbarが実行されることはありませんでも発生します。これは、デコレータの表記法は単に代入の構文的砂糖であるためです。上記のコードは同等です:

def foo(f): 
    print("Decorator foo is executing") 
    return f 

def bar(): 
    pass 
bar = foo(bar) 

「[OK]を、ので、どのように私は関数が呼び出されたときにコードだけ実行するのですか?」あなたは仮説的に尋ねる。これを実現するには、デコレータの定義内に呼び出し可能なオブジェクトを作成して返します。例:

def foo(f): 
    def this_gets_called_when_the_decorated_function_executes(): 
     print("Decorated function is executing") 
     #conventionally, you call the original function in here, but it isn't strictly required 
     f() 
    return this_gets_called_when_the_decorated_function_executes 

@foo 
def bar(): 
    pass 

print("About to call bar.") 
bar() 
print("bar called.") 

結果:

About to call bar. 
Decorated function is executing 
bar called. 
+0

アハ!!!!ありがとう、私はちょうど2番目の内部関数でデコレータを再ラップする必要があり、私は良いはずです。私はそれを試してみましょう –

+0

まあ、あなたのデコレータは_already_呼び出し可能を返す...ときには。これは 'wrapper'を返しますが、ラッパーはstr(key):'ブランチにない ''
''が実行されたときにのみ定義されます。それ以外の場合、 'wrapper'は存在しません。その関数を書いた人は、可能なすべての条件分岐でラッパーが定義されることを保証しなければならないか、あるいは 'else'で他の呼び出し可能なものを返すべきです。 – Kevin

+0

私はラッパー関数の中に他のコードを入れて、今は完全に動作しています。ありがとう –

関連する問題