在"Background work with the deferred library"文章之后,我创建了一组计划任务来帮助维护我们的应用程序。它们各自刷新特定类型的旧实体。在
在一种情况下,我们不使用标准的ndb模型key
属性(用于跟踪已处理的记录),而是使用DateTimeProperty
类型的非键属性。当我们这样做时,当我们点击DeadlineExceededError
时,方法的延迟实例在deferred.run method中的任务参数取消拾取期间死亡。在
基类中的相关代码:
def _continue(self, start_key, batch_size):
# ...
except DeadlineExceededError:
if self._numBatches > 0:
self.Log("Deferring to a new instance of the process.")
deferred.defer(self._continue, start_key, batchSize)
else:
self.LogWarning("No batches were completely processed. This process will terminate to prevent continuous operation.")
raise deferred.PermanentTaskFailure("DeadlineExceededError occurred before any batches could be completely processed.")
self.Finish()
当方法的延迟副本启动时,会产生以下错误:
^{pr2}$更多的挖掘(pdb
通过deferred
和pickle
库)揭示了更多的细节:
1080 def load_newobj(self):
1081 args = self.stack.pop()
1082 cls = self.stack[-1]
1083 -> obj = cls.__new__(cls, *args)
1084 self.stack[-1] = obj
1085 dispatch[NEWOBJ] = load_newobj
以及
(Pdb) pp args
()
(Pdb) pp cls
<class 'google.appengine.ext.ndb.query.FilterNode'>
(Pdb) n
TypeError: '__new__() takes exactly 4 arguments (1 given)'
> /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py(1083)load_newobj()
我会继续挖掘,但现在的基本问题似乎是:
deferred.TaskHandler
(在v.1.6.3 - Feb 28, 2012中介绍的)的提示,这可能有助于解决第一个问题,但找不到任何关于如何做到这一点的示例。在
从
deferred.py
的源代码可以看出,您已经与@rdodev一起进行了很好的分析,以认识到问题是当试图将data
参数解压为run()
时。这又是从run_from_request()
调用的,所以这里没有处理的是请求负载本身,它是在调用deferred.defer()
时创建的。在为了使
DateTimeProperty
被取消pickle,pickle模块可能需要调用它的构造函数(__new__
),但这是不可用的,或者在那时呈现了一个与它被pickle时不同的方法签名,从而导致您看到的异常,该异常将被捕获并以PermanentTaskFailure
的形式呈现给您。在总的来说,如果您可以生成一个可靠地复制行为的示例应用程序,那么这可能值得作为缺陷报告发布到public issue tracker。在
除此之外,作为一个暂时的解决方法,我将使用一些不会导致错误的东西,比如
DateTimeProperty
的字符串表示,或者一个常规的datetime.datetime
对象,甚至是另一个不会引起问题的ndb.Property
类。您还可以尝试使用taskqueue library本身,这是非常容易使用的,不应该代表与当前用例的显著偏离。在相关问题 更多 >
编程相关推荐