如何在 GAE (Google App Engine) 中使用 Python main() 函数?
How to use Python main() function in GAE (Google App Engine)?
我想在我的 GAE 代码中使用 main()
函数
(注意:下面的代码只是一个更大程序的最小演示,因此需要 main()
).
如果我使用以下代码,它会按预期执行:
import webapp2
class GetHandler(webapp2.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.write('in GET')
class SetHandler(webapp2.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.write('in SET')
app = webapp2.WSGIApplication([
('/get', GetHandler),
('/set', SetHandler),
], debug=True)
我的 app.yaml
是:
runtime: python27
api_version: 1
threadsafe: true
handlers:
- url: /.*
script: main.app
但是,我无法弄清楚如何实现 main()
函数,并且 app
仍像顶部代码中那样工作.即,以下内容:
# with main()
import webapp2
class GetHandler(webapp2.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.write('in GET')
class SetHandler(webapp2.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.write('in SET')
def main():
app = webapp2.WSGIApplication([
('/get', GetHandler),
('/set', SetHandler),
], debug=True)
if __name__ == '__main__':
main()
为http://localhost:8080/get:
给出以下错误
$ dev_appserver.py .
INFO 2016-10-17 11:29:30,962 devappserver2.py:769] Skipping SDK update check.
INFO 2016-10-17 11:29:31,059 api_server.py:205] Starting API server at: http://localhost:45865
INFO 2016-10-17 11:29:31,069 dispatcher.py:197] Starting module "default" running at: http://localhost:8080
INFO 2016-10-17 11:29:31,073 admin_server.py:116] Starting admin server at: http://localhost:8000
ERROR 2016-10-17 11:29:37,461 wsgi.py:263]
Traceback (most recent call last):
File "/home/.../sdk/platform/google_appengine/google/appengine/runtime/wsgi.py", line 240, in Handle
handler = _config_handle.add_wsgi_middleware(self._LoadHandler())
File "/home/.../sdk/platform/google_appengine/google/appengine/runtime/wsgi.py", line 302, in _LoadHandler
raise err
ImportError: <module 'main' from '/home/.../main.pyc'> has no attribute app
INFO 2016-10-17 11:29:37,496 module.py:788] default: "GET /get HTTP/1.1" 500 -
编辑 1
正在尝试:
# with main()
import webapp2
app = webapp2.RequestHandler()
class GetHandler(webapp2.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.write('in GET')
class SetHandler(webapp2.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.write('in SET')
def main():
global app
app = webapp2.WSGIApplication([
('/get', GetHandler),
('/set', SetHandler),
], debug=True)
return app
if __name__ == '__main__':
app = main()
结果:
INFO 2016-10-17 12:30:34,751 module.py:402] [default] Detected file changes:
/home/openstack/googleAppEngine/fastsimon/task2/task2_with_main/main.py
ERROR 2016-10-17 12:30:42,328 wsgi.py:279]
Traceback (most recent call last):
File "/home/openstack/googleAppEngine/google-cloud-sdk/platform/google_appengine/google/appengine/runtime/wsgi.py", line 267, in Handle
result = handler(dict(self._environ), self._StartResponse)
TypeError: 'RequestHandler' object is not callable
INFO 2016-10-17 12:30:42,335 module.py:788] default: "GET /get HTTP/1.1" 500 -
GAE 应用并非设计为独立应用,main()
功能对它们来说意义不大。
基本上,GAE 应用程序实际上只是处理程序代码的集合,rules/configurations 旨在扩展和自定义通用 GAE infra/sandbox 代码的行为,以便它可以运行您的应用程序。您可以从您的回溯中看到 - 其他代码正在调用您的处理程序代码(并且到达您的代码之前的堆栈可能比那更深)。
在您的特定情况下,app
变量 必须 是 main.py
中的全局变量,以匹配 [=] 中的 script: main.app
配置行14=] 配置文件。这就是回溯的内容。
至于组织大型应用程序的代码,还有其他方法:
将应用拆分为多个 modules/services, each with their own app.yaml
config file. For example:
将一个 service/module 拆分为多个 "scripts" - app.yaml
文件的主要入口点类似于您的 main.py
文件,每个入口点都有自己的app
config` - 实际上只是路由和处理程序之间的映射器。例如:
使用 webapp2 的延迟加载处理程序技术将一个 app
映射器的处理程序拆分为多个文件。示例:
- What determines start up time of dynamic instance and can it vary between weeks if code is same
在极端情况下,main.py
文件可能只包含 app
变量 - 这确实是唯一的要求。
似乎解决方案非常简单(它一直在躲避我,因为它隐藏在众目睽睽之下):__name__
是 main 而不是 __main__!
简而言之,以下代码按预期使用了 main()
:
# with main()
import webapp2
class GetHandler(webapp2.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.write('in GET')
class SetHandler(webapp2.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.write('in SET')
def main():
global app
app = webapp2.WSGIApplication([
('/get', GetHandler),
('/set', SetHandler),
], debug=True)
# Note that it's 'main' and not '__main__'
if __name__ == 'main':
main()
https://webapp2.readthedocs.io/en/latest/tutorials/quickstart.nogae.html 描述了如何在 GAE 环境之外使用 GAE 应用程序:
from myapp import app
def main():
from paste import httpserver
httpserver.serve(app, host='localhost', port='8070')
if __name__ == '__main__':
main()
我这样做是为了使用 Pycharm IDE 而不是 dev_appserver 命令 window 来调试我的应用程序;它工作正常。我将结果与端口 8080 上的 dev_appserver 运行 和 8070 上的调试器 运行 进行比较。
我想在我的 GAE 代码中使用 main()
函数
(注意:下面的代码只是一个更大程序的最小演示,因此需要 main()
).
如果我使用以下代码,它会按预期执行:
import webapp2
class GetHandler(webapp2.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.write('in GET')
class SetHandler(webapp2.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.write('in SET')
app = webapp2.WSGIApplication([
('/get', GetHandler),
('/set', SetHandler),
], debug=True)
我的 app.yaml
是:
runtime: python27
api_version: 1
threadsafe: true
handlers:
- url: /.*
script: main.app
但是,我无法弄清楚如何实现 main()
函数,并且 app
仍像顶部代码中那样工作.即,以下内容:
# with main()
import webapp2
class GetHandler(webapp2.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.write('in GET')
class SetHandler(webapp2.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.write('in SET')
def main():
app = webapp2.WSGIApplication([
('/get', GetHandler),
('/set', SetHandler),
], debug=True)
if __name__ == '__main__':
main()
为http://localhost:8080/get:
$ dev_appserver.py .
INFO 2016-10-17 11:29:30,962 devappserver2.py:769] Skipping SDK update check.
INFO 2016-10-17 11:29:31,059 api_server.py:205] Starting API server at: http://localhost:45865
INFO 2016-10-17 11:29:31,069 dispatcher.py:197] Starting module "default" running at: http://localhost:8080
INFO 2016-10-17 11:29:31,073 admin_server.py:116] Starting admin server at: http://localhost:8000
ERROR 2016-10-17 11:29:37,461 wsgi.py:263]
Traceback (most recent call last):
File "/home/.../sdk/platform/google_appengine/google/appengine/runtime/wsgi.py", line 240, in Handle
handler = _config_handle.add_wsgi_middleware(self._LoadHandler())
File "/home/.../sdk/platform/google_appengine/google/appengine/runtime/wsgi.py", line 302, in _LoadHandler
raise err
ImportError: <module 'main' from '/home/.../main.pyc'> has no attribute app
INFO 2016-10-17 11:29:37,496 module.py:788] default: "GET /get HTTP/1.1" 500 -
编辑 1
正在尝试:
# with main()
import webapp2
app = webapp2.RequestHandler()
class GetHandler(webapp2.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.write('in GET')
class SetHandler(webapp2.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.write('in SET')
def main():
global app
app = webapp2.WSGIApplication([
('/get', GetHandler),
('/set', SetHandler),
], debug=True)
return app
if __name__ == '__main__':
app = main()
结果:
INFO 2016-10-17 12:30:34,751 module.py:402] [default] Detected file changes:
/home/openstack/googleAppEngine/fastsimon/task2/task2_with_main/main.py
ERROR 2016-10-17 12:30:42,328 wsgi.py:279]
Traceback (most recent call last):
File "/home/openstack/googleAppEngine/google-cloud-sdk/platform/google_appengine/google/appengine/runtime/wsgi.py", line 267, in Handle
result = handler(dict(self._environ), self._StartResponse)
TypeError: 'RequestHandler' object is not callable
INFO 2016-10-17 12:30:42,335 module.py:788] default: "GET /get HTTP/1.1" 500 -
GAE 应用并非设计为独立应用,main()
功能对它们来说意义不大。
基本上,GAE 应用程序实际上只是处理程序代码的集合,rules/configurations 旨在扩展和自定义通用 GAE infra/sandbox 代码的行为,以便它可以运行您的应用程序。您可以从您的回溯中看到 - 其他代码正在调用您的处理程序代码(并且到达您的代码之前的堆栈可能比那更深)。
在您的特定情况下,app
变量 必须 是 main.py
中的全局变量,以匹配 [=] 中的 script: main.app
配置行14=] 配置文件。这就是回溯的内容。
至于组织大型应用程序的代码,还有其他方法:
将应用拆分为多个 modules/services, each with their own
app.yaml
config file. For example:将一个 service/module 拆分为多个 "scripts" -
app.yaml
文件的主要入口点类似于您的main.py
文件,每个入口点都有自己的app
config` - 实际上只是路由和处理程序之间的映射器。例如:使用 webapp2 的延迟加载处理程序技术将一个
app
映射器的处理程序拆分为多个文件。示例:- What determines start up time of dynamic instance and can it vary between weeks if code is same
在极端情况下,main.py
文件可能只包含 app
变量 - 这确实是唯一的要求。
似乎解决方案非常简单(它一直在躲避我,因为它隐藏在众目睽睽之下):__name__
是 main 而不是 __main__!
简而言之,以下代码按预期使用了 main()
:
# with main()
import webapp2
class GetHandler(webapp2.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.write('in GET')
class SetHandler(webapp2.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.write('in SET')
def main():
global app
app = webapp2.WSGIApplication([
('/get', GetHandler),
('/set', SetHandler),
], debug=True)
# Note that it's 'main' and not '__main__'
if __name__ == 'main':
main()
https://webapp2.readthedocs.io/en/latest/tutorials/quickstart.nogae.html 描述了如何在 GAE 环境之外使用 GAE 应用程序:
from myapp import app
def main():
from paste import httpserver
httpserver.serve(app, host='localhost', port='8070')
if __name__ == '__main__':
main()
我这样做是为了使用 Pycharm IDE 而不是 dev_appserver 命令 window 来调试我的应用程序;它工作正常。我将结果与端口 8080 上的 dev_appserver 运行 和 8070 上的调试器 运行 进行比较。