2012-10-24 63 views
1

我試圖學習圍繞這些新穎的「工廠」式網絡庫的方法。 Twisted帶來了很多好評,但對我來說卻是一場絕對的噩夢,因爲我對lambda不熟悉,因此我真的不確定如何遵循演示代碼的做法。扭曲/放大器聯網:迴應所有客戶,而不僅僅是一個請求

演示客戶端:

from twisted.internet import reactor, defer 
from twisted.internet.protocol import ClientCreator 
from twisted.protocols import amp 
from ampserver import Sum, Divide 


def doMath(): 
    d1 = ClientCreator(reactor, amp.AMP).connectTCP(
     '127.0.0.1', 1234).addCallback(
      lambda p: p.callRemote(Sum, a=13, b=81)).addCallback(
       lambda result: result['total']) 
    def trapZero(result): 
     result.trap(ZeroDivisionError) 
     print "Divided by zero: returning INF" 
     return 1e1000 
    d2 = ClientCreator(reactor, amp.AMP).connectTCP(
     '127.0.0.1', 1234).addCallback(
      lambda p: p.callRemote(Divide, numerator=1234, 
            denominator=0)).addErrback(trapZero) 
    def done(result): 
     print 'Done with math:', result 
    defer.DeferredList([d1, d2]).addCallback(done) 

if __name__ == '__main__': 
    doMath() 
    reactor.run() 

演示服務器:

from twisted.protocols import amp 

class Sum(amp.Command): 
    arguments = [('a', amp.Integer()), 
       ('b', amp.Integer())] 
    response = [('total', amp.Integer())] 


class Divide(amp.Command): 
    arguments = [('numerator', amp.Integer()), 
       ('denominator', amp.Integer())] 
    response = [('result', amp.Float())] 
    errors = {ZeroDivisionError: 'ZERO_DIVISION'} 


class Math(amp.AMP): 
    def sum(self, a, b): 
     total = a + b 
     print 'Did a sum: %d + %d = %d' % (a, b, total) 
     return {'total': total} 
    Sum.responder(sum) 

    def divide(self, numerator, denominator): 
     result = float(numerator)/denominator 
     print 'Divided: %d/%d = %f' % (numerator, denominator, result) 
     return {'result': result} 
    Divide.responder(divide) 


def main(): 
    from twisted.internet import reactor 
    from twisted.internet.protocol import Factory 
    pf = Factory() 
    pf.protocol = Math 
    reactor.listenTCP(1234, pf) 
    print 'started' 
    reactor.run() 

if __name__ == '__main__': 
    main() 

據我瞭解,客戶端p.callRemote(Sum, a=13, b=81)p.callRemote(Divide, numerator=1234, denominator=0)部分叫Math.sum(13, 81)Math.Divide(1234, 0),因爲工廠對象的設置爲Math類。不知何故,當客戶端收到來自服務器的返回值時,子功能Done(result)被調用,它將東西打印到屏幕上。

這很棒,但是我的理解很糟糕,而且每一篇文檔似乎都期望達到這種理解水平。

我真正想要做的是將數據從客戶端發送到服務器,並從服務器發送到連接的多個客戶端。一旦交換結束,這種方法似乎會忘記客戶端,並阻止客戶端進行任何其他工作。

人們可能希望每一天都可以使用此功能。我如何理解這一點?

編輯:我試圖爲客戶端調用一個「檢查」功能,但這似乎是它會淹沒我的服務器的請求只是迴應「沒有報告」。此外,它增加了延遲,因爲客戶端只在需要時收到新數據,而不是實際可用時。工廠 - 反應器佈局似乎沒有公開我需要存儲的客戶信息,以便隨意對其進行響應。

+0

Lambda是一種定義函數而不給它命名的方法;一個匿名函數。文檔顯示了它們與功能的關係。 http://docs.python.org/reference/expressions.html#lambda話雖如此,我認爲使用'CLientCreator'的'doMath()'中的代碼相當糟糕。它違反了「Python的禪宗」(嘗試在交互式Python會話中導入該文件)。 –

+0

@RolandSmith,您對Twisted示例質量的看法將通過http://twistedmatrix.com/trac/newticket更有建設性地表達爲文檔缺陷報告。我不會說文檔是完美的,但提問者試圖理解的例子的質量與問題無關。 – Glyph

+0

@RolandSmith @RolandSmith這不是一個嚴格的lambdas精確定義,因爲它還有一些巧妙的變量範圍 – Basic

回答

1

你似乎有三個問題: 「是什麼意思lambda Python中的」

  1. 這是covered by Python's documentation。如果您仍然難以閱讀以這種方式編寫的代碼,則可以使用lambda x: y只是編寫def my_function(x): return y的快捷方式。任何地方,你看到一個lambda,例如像這樣:

    def foo(bar): 
        return boz().addCallback(lambda result: qux(bar, result)) 
    

    可以隨時拔出lambda到它自己的功能,因此,它更容易讓你看,像這樣:

    def foo(bar): 
        def callback_for_boz(result): 
         return qux(bar, result) 
        return boz().addCallback(callback_for_boz) 
    
  2. How do I make input on one connection result in output on another?

    這是documented by Twisted's FAQ

  3. How do I make Twisted talk to multiple clients/connect to multiple servers?

    這是also a twisted FAQ。這裏的一般想法是,reactor.run()的意思是「......然後運行整個程序」。在reactor.run()之前運行任何代碼的唯一原因是設置初始定時器,偵聽套接字或第一個連接。無論是在運行反應堆之前,還是在稍後在程序中發生的任何回調中,您都可以隨時撥打connectTCPlistenTCP

+1

感謝您提供常見問題解答鏈接,自發帖以來,我已經偶然發現了#2,但沒有找到#3,我會好好研究它們。 爲了您對#3的評論,我應該認爲它是不好的風格,將'reactor.run()'封裝在一個單獨的線程中,通過隊列或類似的方式與扭曲的函數進行交互? – John

+0

我會毫不猶豫地稱之爲「壞」風格,因爲它取決於你的要求,但所有的東西都是平等的,通常使用Twisted「本地」更好,並且在主線程上運行一次'reactor.run'。在非主線程上運行它會中斷子進程產卵,當您想要關閉時會打開各種類似惡夢的信號/線程交互,並且通常是您應該有很好理由處理的頭痛問題。此外,您不能使用'Queue'與Twisted以這種方式進行交互:使用'reactor.callInThread' /'callfromThread'。 – Glyph

+0

如果你認爲這回答你的問題,順便說一句,你應該「接受」答案(大綠色的複選標記)。 – Glyph

相關問題