浏览代码

Adding example of decorator

Swaroop C H 12 年之前
父节点
当前提交
47035101b6
共有 1 个文件被更改,包括 72 次插入0 次删除
  1. 72 0
      17-more.md

+ 72 - 0
17-more.md

@@ -221,6 +221,78 @@ The `assert` statement should be used judiciously. Most of the time,
 it is better to catch exceptions, either handle the problem or display
 it is better to catch exceptions, either handle the problem or display
 an error message to the user and then quit.
 an error message to the user and then quit.
 
 
+## Decorators ##
+
+Decorators are a shortcut to applying wrapper functions. This is
+helpful to "wrap" functionality with the same code over and over
+again. For example, I created a `retry` decorator for myself that I
+can just apply to any function and if any exception is thrown during a
+run, it is retried again, till a maximum of 5 times and with a delay
+between each retry. This is especially useful for situations where you
+are trying to make a network call to a remote computer:
+
+~~~python
+from time import sleep
+from functools import wraps
+import logging
+logging.basicConfig()
+log = logging.getLogger("retry")
+
+
+def retry(f):
+    @wraps(f)
+    def wrapped_f(*args, **kwargs):
+        MAX_ATTEMPTS = 5
+        for attempt in range(1, MAX_ATTEMPTS + 1):
+            try:
+                return f(*args, **kwargs)
+            except:
+                log.exception("Attempt %s/%s failed : %s",
+                              attempt,
+                              MAX_ATTEMPTS,
+                              (args, kwargs))
+                sleep(10 * attempt)
+        log.critical("All %s attempts failed : %s",
+                     MAX_ATTEMPTS,
+                     (args, kwargs))
+    return wrapped_f
+
+
+counter = 0
+
+
+@retry
+def save_to_database(arg):
+    print("Write to a database or make a network call or etc.")
+    print("This will be automatically retried if exception is thrown.")
+    global counter
+    counter += 1
+    if counter < 2:
+        raise ValueError(arg)
+
+
+if __name__ == '__main__':
+    save_to_database("Some bad value")
+~~~
+
+Output:
+
+~~~
+$ python3 retry_decorator.py
+
+Write to a database or make a network call or etc.
+This will be automatically retried if exception is thrown.
+ERROR:retry:Attempt 1/5 failed : (('Some bad value',), {})
+Traceback (most recent call last):
+  File "/tmp/retry_decorator.py", line 14, in wrapped_f
+    return f(*args, **kwargs)
+  File "/tmp/retry_decorator.py", line 37, in save_to_database
+    raise ValueError(arg)
+ValueError: Some bad value
+Write to a database or make a network call or etc.
+This will be automatically retried if exception is thrown.
+~~~
+
 ## Differences between Python 2 and Python 3 ##
 ## Differences between Python 2 and Python 3 ##
 
 
 Read these articles:
 Read these articles: