PermanentTaskFailure:__ new __()需要4个参数(由于DateTimePropety?)

时间:2015-06-23 14:32:46

标签: python google-app-engine pickle deferred

"Background work with the deferred library"文章之后,我创建了一组计划任务来帮助维护我们的应用。它们每个都刷新特定类型的旧实体。

在一种情况下,我们使用类型为key的非键属性,而不是使用标准的ndb模型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()

当方法的延迟副本启动时,会产生此错误:

Traceback (most recent call last):
    File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/deferred/deferred.py", line 310, in post
        self.run_from_request()
    File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/deferred/deferred.py", line 305, in run_from_request
        run(self.request.body)
    File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/deferred/deferred.py", line 145, in run
        raise PermanentTaskFailure(e)
    PermanentTaskFailure: __new__() takes exactly 4 arguments (1 given)

通过pdbdeferred库进行更多挖掘(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()

我正在挖掘更多,但现在的基本问题似乎是:

  1. 除了pdb之外,如何获得有关此阶段发生故障的更多信息(例如:deferred.run和unpickling)?
  2. 我在网上发现了一些关于覆盖deferred.TaskHandler的能力的提示(在v.1.6.3 - Feb 28, 2012中引入),这可能有助于解决第一个问题,但找不到任何关于如何执行此操作的示例。
  3. 似乎ndb具有DateTimeProperty的FilterNodes默认情况下可能无法选择(或正确处理)。是这样吗?

1 个答案:

答案 0 :(得分:0)

deferred.py的来源可以看出,您与@rdodev一起分析得很好,意识到问题是在尝试取消data参数{ {1}}。这反过来是从run()调用的,所以这里未被腌制的是请求有效负载本身,它是在您调用run_from_request()时创建的。

对于deferred.defer()未被腌制,pickle模块可能需要为其调用构造函数(DateTimeProperty),但这不可用或者当时提供的方法签名与腌制时的方法签名不同,导致您看到的异常,这些气泡会被捕获并呈现给__new__

总的来说,如果您可以生成可靠地重现行为的示例应用程序,那么这可能值得作为缺陷报告发布到public issue tracker

除此之外,作为现在的解决方法,我使用了不会导致错误的内容,例如PermanentTaskFailure的字符串表示形式或常规{{ 1}}对象,甚至是另一个DateTimeProperty类,它不会引起问题。您也可以尝试使用taskqueue library本身,它非常易于使用,并且不应与您当前的用例有很大的不同。