V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Tornado Documentation
http://www.v2ex.com/tornado/
Tornado on GitHub
https://github.com/facebook/tornado/
Tornado Gists
http://tornadogists.org/
wolegequ
V2EX  ›  Tornado

finish() called twice

  •  
  •   wolegequ · 2015-06-17 17:18:49 +08:00 · 5516 次点击
    这是一个创建于 3454 天前的主题,其中的信息可能已经有所发展或是发生改变。
    抱歉,标题略含糊.

    有两个返回json接口
    http://example.com/api/user/uid
    http://example.com/api/user/uid/fun

    本打算如此实现 handles
    (r'/api/user/(.*)', user.fun1),
    (r'/api/user/(.*)/fun2', user.fun2 ),

    搞了半天,发现 user.fun1 根本不会调用 ......

    于是乎改为这样

    (r'/api/user/(.*)', user.funs ),


    class funs(BaseController):

    @tornado.web.asynchronous
    def get(self, params):

    if 'fun' in params:
    self.fun2
    else:
    self.fun1

    惊奇的发现 it works !!!(虽然很山寨...)

    重点来了 !!!!

    客户端两个接口先后几乎同时请求

    self.fun1 self.fun2最后都会调用 self.finish(),

    于是乎出现了 finish() called twice - - !

    后来看到有说法@tornado.web.asynchronous 是不可以self.finish()的

    于是乎改为self.fun1 self.fun2最后都调用 self.write(),

    没有 finish() called twice了,但是有一个接口一直没数据返回(单独请求任意一个都正常!)

    醉了醉了....
    第 1 条附言  ·  2015-06-18 14:41:37 +08:00
    感谢@aiden0xz @msg7086 @janxin 的指点,确实应该用正则表达式

    后来改成了这样( len(uid) == 32 )

    http://example.com/api/user/[0-9a-z]{32}
    http://example.com/api/user/[0-9a-z]{32}/fun
    http://example.com/api/user/[0-9a-z]{32}/a
    http://example.com/api/user/[0-9a-z]{32}/b

    class user(BaseController):

    @tornado.web.asynchronous
    def get(self, uid):
    pass

    class fun(BaseController):

    @tornado.web.asynchronous
    def get(self, uid):
    pass

    在fun传进uid居然是 'uid/fun' !!!



    @tigerstudent 我的意思是,假如某个接口会有比较密集的请求,tornado会对
    每一个请求单独实例化一份对应的controller不?
    第 2 条附言  ·  2015-06-19 01:53:42 +08:00
    [结帖]

    http://example.com/api/user/[0-9a-z]{32}
    http://example.com/api/user/[0-9a-z]{32}/fun
    http://example.com/api/user/[0-9a-z]{32}/a
    http://example.com/api/user/[0-9a-z]{32}/b

    这几个接口会调用不同的controller, 但是处理数据的时候调用的同一个model,

    而我把这个实例化为全局变量了....

    [解决方式]
    controller 单独实例化需要的 model
    13 条回复    2015-06-19 01:54:43 +08:00
    yangtukun1412
        1
    yangtukun1412  
       2015-06-17 17:55:32 +08:00
    文档里并没有说加了 asynchronous 装饰器的方法不能使用 self.finish(),相反的,加了装饰器后是需要显式调用 finish 方法才会完成请求的。

    所以问题还是要看你的 fun1 和 fun2 里面到底做了什么...
    wolegequ
        2
    wolegequ  
    OP
       2015-06-17 18:03:54 +08:00
    @yangtukun1412 fun1 和 fun2 都调用http接口取得数据, 处理完毕再返回给客户端
    ltttx
        3
    ltttx  
       2015-06-17 18:10:19 +08:00
    问题在于你的url配置问题,前者的正则匹配太宽泛了
    wolegequ
        4
    wolegequ  
    OP
       2015-06-17 18:16:46 +08:00
    @aiden0xz 此类该如何配置呀,求指点...
    wolegequ
        6
    wolegequ  
    OP
       2015-06-17 21:53:41 +08:00
    @aiden0xz 换行直接回复了....

    历史原因导致的....

    http://example.com/api/user/uid
    http://example.com/api/user/uid/fun
    http://example.com/api/user/uid/a
    http://example.com/api/user/uid/b

    有此类的接口,路由设置貌似没效果
    tigerstudent
        7
    tigerstudent  
       2015-06-17 23:09:27 +08:00
    “客户端两个接口先后几乎同时请求

    self.fun1 self.fun2最后都会调用 self.finish(),

    于是乎出现了 finish() called twice - - ! ”
    按你前面的描述,if else分开的self.fun1 self.fun2怎么会两个都执行?
    msg7086
        9
    msg7086  
       2015-06-18 07:37:44 +08:00
    为什么要用(.*)?用([0-9]+)不行吗?
    tigerstudent
        10
    tigerstudent  
       2015-06-18 08:38:40 +08:00 via Android
    @wolegequ 两个请求之间不会有冲突!你想歪了!
    ltttx
        11
    ltttx  
       2015-06-18 08:55:16 +08:00
    @wolegequ 参考 @msg7086
    janxin
        12
    janxin  
       2015-06-18 09:15:23 +08:00
    url匹配的话,应该是正则写的太松了,导致的匹配问题,一般[0-9a-zA-z]应该能满足需求。
    self.finish应该是需要调用的吧,如果是render或者redirect,应该已经调用过self.finish了,不需要显示调用。self.write需要显示调用self.finish。不过我倒是一般用@tornado.gen.corountine
    wolegequ
        13
    wolegequ  
    OP
       2015-06-19 01:54:43 +08:00
    问题已解决, 多谢各位
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2506 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 33ms · UTC 05:01 · PVG 13:01 · LAX 21:01 · JFK 00:01
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.