我正在使用最新版本的GAE,包括自动扩展,端点API和deferred.defer()任务。
问题在于,自添加API以来,有些实例会自动启动,总是会导致永久性任务失败:
Permanent failure attempting to execute task
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: No module named app.Report
永久任务失败对于单个实例是唯一的,其中该实例上的每个延迟任务都会失败。即使任务没有使用Api.py模块,这些延迟任务都会抛出相同的错误。在其他情况下,如果相同的延迟任务没有路由到失败的实例,它们将运行得很好。
app.yaml处理程序如下所示:
handlers:
# Api Handler
- url: /_ah/api/.*
script: main.api
- url: /_ah/spi/.*
script: main.api
# All other traffic
- url: .*
script: main.app
builtins:
- deferred: on
main.py看起来像:
import Api, endpoints, webapp2
api = endpoints.api_server([Api.AppApi])
app = webapp2.WSGIApplication(
[(misc routes)]
,debug=True)
Api.py看起来像:
import endpoints
from protorpc import messages
from protorpc import message_types
from protorpc import remote
from google.appengine.ext import deferred
from app.Report import ETLScheduler
@endpoints.api(...)
class AppApi(remote.Service):
@endpoints.method(...)
def reportExtract(self, request):
deferred.defer(
ETLScheduler,
params
)
我没有进行任何路径修改,所以我很好奇为什么新实例无法找到API的python模块,即使延迟任务在另一个模块中使用其他功能。为什么它只会为该实例抛出这些错误?
修改
因此,在查看了其他一些SO问题之后,我尝试在appengine_config.py
中进行路径修改。我将所有文件夹移动到lib
目录,并将其添加到配置文件中:
import os,sys
sys.path.append(os.path.join(os.path.dirname(__file__), 'lib'))
现在我在失败的实例上遇到的错误是:
Permanent failure attempting to execute task
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: cannot import name ETLScheduler
所以它似乎在寻找模块,但与之前一样,实例上的延迟任务都不能导入该方法。
答案 0 :(得分:1)
所以我找到了一种让它工作的方法,但我不确定它为什么会起作用。
通过导入整个模块而不是模块中的方法,为延迟任务启动的新实例不再抛出PermanentTaskFailure: cannot import name ETLScheduler
错误。
我尝试导入整个模块而不是方法,因此Api.py看起来像这样:
import endpoints
from protorpc import messages
from protorpc import message_types
from protorpc import remote
from google.appengine.ext import deferred
# Import the module instead of the method
#from app.Report import ETLScheduler
import app.Report
@endpoints.api(...)
class AppApi(remote.Service):
@endpoints.method(...)
def reportExtract(self, request):
deferred.defer(
app.Report.ETLScheduler,
params
)
现在我不再获得抛出PermanentTaskFailure: cannot import name ETLScheduler
的实例。可能是在main.py中导入Api.py的循环依赖(我不确定),但至少它现在可以正常工作。
答案 1 :(得分:-1)
如果您尝试在特定模块中运行某些内容,则在延迟调用中错过了_target kwarg。
deferred.defer(
app.Report.ETLScheduler,
params,
_target="modulename"
)