【问题标题】:How to use Python main() function in GAE (Google App Engine)?如何在 GAE(Google App Engine)中使用 Python main() 函数?
【发布时间】:2017-02-26 09:17:52
【问题描述】:

我想在我的 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 -

【问题讨论】:

  • 为什么要这样做?有什么意义?
  • 正如我提到的(第 1 段),我有许多需要实现的处理程序,并且在我的应用程序中将它们保存在一个单独的函数中更加有序。我要求在 GAE 中使用 main() 是不可能的吗,@Daniel?
  • 这篇文章解释了原因:blog.notdot.net/2011/10/…
  • @boardrider你可以跨函数和文件实现你的应用,我还是不明白你为什么要使用main()

标签: python python-2.7 google-app-engine main wsgi


【解决方案1】:

GAE 应用并非设计为独立应用,main() 函数对它们没有多大意义。

基本上,GAE 应用程序实际上只是处理程序代码和规则/配置的集合,旨在扩展和自定义通用 GAE 基础设施/沙盒代码的行为,以便它运行您的应用程序。您可以从您的回溯中看到 - 其他代码正在调用您的处理程序代码(到达您的代码之前的堆栈可能比这更深)。

在您的特定情况下,app 变量必须main.py 中的全局变量,以匹配app.yaml 配置文件中的script: main.app 配置行。这就是回溯的意义所在。

对于大型应用程序的代码组织,还有其他方法:

在极端情况下,main.py 文件可能包含 app 变量 - 这确实是唯一的要求。

【讨论】:

    【解决方案2】:

    似乎解决方案很简单(它一直躲避我,因为它隐藏在明显的视线中):__name__ma​​in 而不是 __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()
    

    【讨论】:

      【解决方案3】:

      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 命令窗口调试我的应用程序;它工作正常。我将结果与在端口 8080 上运行的 dev_appserver 和在 8070 上运行的调试器进行比较。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-09-11
        • 2014-06-22
        • 2013-07-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-11
        相关资源
        最近更新 更多