如果我能在返回结果后在函数中做更多的工作,我有点好奇.基本上我在使用金字塔框架(简单地在python中编码)创建一个网站后我处理输入我返回变量来呈现页面但有时我想在渲染页面后做更多的工作.
例如,您来到我的网站并更新您的个人资料,所有您关心的是它的成功,所以我输出一条消息说"成功!" 但在完成之后我想接受你的更新并更新你的活动日志,更新你的朋友活动流等等.现在我正在做所有这些,然后我返回你关心的结果状态,但我'我很好奇,如果我能做到这一点,那么用户可以更快地得到他们的回复.
我之前已经完成了多处理,最糟糕的情况是我可能只是分叉一个线程来完成这项工作,但是如果有一种方法在return语句之后继续工作那么那会更简单.
例:
def profile_update(inputs):
#take updates and update the database
return "it worked"
#do maintainence processing now..
Run Code Online (Sandbox Code Playgroud)
Jef*_*ner 17
你为什么不使用上下文管理器?它基本上完全符合你的要求.
这是Python文档中的规范示例.
from contextlib import contextmanager
@contextmanager
def tag(name):
print "<%s>" % name
yield
print "</%s>" % name
Run Code Online (Sandbox Code Playgroud)
所以对于你的功能,你只需:
@contextmanager
def profile_update(inputs):
#take updates and update the database
yield "it worked"
#do maintainence processing now..
Run Code Online (Sandbox Code Playgroud)
打电话给你,你只需:
with profile_update(inputs) as result: #pre-yield and yield here
# do whatever while in scope
# as you move out of scope of with statement, post-yield is executed
Run Code Online (Sandbox Code Playgroud)
编辑:我只是测试了一些事情,事实证明,使用yield语句,函数仍然执行到最后.这是一个愚蠢的例子,说明了事情的执行点.
def some_generator(lst):
for elem in lst:
yield elem
lst[0] = "I WAS CHANGED POST-YIELD!!!!"
>>> q = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> gen = some_generator(q)
>>> for e in gen:
... print e, q
0 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
1 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
2 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
3 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
4 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
5 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
6 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
7 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
8 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
9 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print q
['I WAS CHANGED POST YIELD!!!', 1, 2, 3, 4, 5, 6, 7, 8, 9]
Run Code Online (Sandbox Code Playgroud)
contextmanager的优点是不需要两次next调用来进行stop迭代(和更清晰的语法),但是如果你想返回多个值或者其他东西,你也可以这样做,但你可以看到post yield语句实际上直到生成器在next调用时引发StopIteration 时才会被调用(for循环结束时for循环结束StopIteration)
如果由于某种原因,您需要比@contextmanager提供更高程度的控制,您还可以使用__enter__和__exit__方法定义一个类:
class MyContextClass(object):
# ...
def __enter__(self):
# do some preprocessing
return some_object
def __exit__(self, exc_type, exc_value, traceback):
# do some post processing
# possibly do some processing of exceptions raised within the block
if exc_type == MyCustomErrorType:
return True #don't propagate the error
Run Code Online (Sandbox Code Playgroud)
Gie*_*iel 13
如果从try-block返回,你仍然可以在返回后做一些工作,finally块仍然会被执行,例如:
def fun():
try:
return
finally:
print "Yay! I still got executed, even though my function has already returned!"
Run Code Online (Sandbox Code Playgroud)
引用文档:
当return返回带有finally子句的try语句控制时,该finally子句在真正离开函数之前执行.
import threading
def profile_update(inputs):
# call function to take updates and update the database
update_function(inputs)
# call the maintainence_function here
t = threading.Thread(target=maintainence_function, args=[input1, input2])
# setDaemon=False to stop the thread after complete
t.setDaemon(False)
# starting the thread
t.start()
# return response/anything-else you want to return
return "it worked"
def update_function(inputs):
# updating the database process here
def maintainence_function(input1, input2):
#do maintainence processing now..
Run Code Online (Sandbox Code Playgroud)
这里我们使用python的线程功能。
首先我们调用更新函数(如果需要,如果响应不依赖于这个函数,如果你需要立即给出响应,你也可以在线程中使用这个函数)。
然后我们创建了一个线程,该线程将完成maintenance_function 函数并在完成后停止。但响应不会延迟,直到该功能完成。
即:返回“它工作”将被返回,然后如果ts一个位进程,线程也会维护函数maintenance_function的工作。
不,返回值会将值返回给调用方并停止。
如果调用方也处于您的控制之下(而不是金字塔框架的一部分),则可以更改profile_updates为如下所示:
def profile_update(inputs):
#take updates and update the database
def post_processing_task():
#do maintainence processing now..
return ("it worked", post_processing_task)
Run Code Online (Sandbox Code Playgroud)
然后对调用方进行编码,以期望一对(response, task),而不仅仅是响应。它可以立即处理response零件(将其传达给用户),然后调用task()以处理后处理。
这允许profile_update确定随后需要执行哪些代码(并使这些细节从更高级别隐藏和封装),但允许更高级别确定将响应传达给用户然后在后台执行后处理的流程。背景。
| 归档时间: |
|
| 查看次数: |
26642 次 |
| 最近记录: |