2015-12-23 61 views
0

我有一個TCP客戶端在我的扭曲應用下面的代碼不同的日誌文件:打印到基於雙絞線中的客戶端應用程序連接

from twisted.internet import reactor, protocol 
from twisted.python import log 
import time 

class EchoClient(protocol.Protocol): 
    def connectionMade(self): 
     if(self.factory.server_name == 'server1'): 
      log.startLogging(open('server1.log','w')) 
     else: 
      log.startLogging(open('server2.log','w')) 
     log.msg("Connected to "+self.factory.server_name) 

    def connectionLost(self,reason): 
     log.msg("Connection is lost " + reason.getErrorMessage()) 

    def dataReceived(self,data): 
     log.msg("Server said: " + data) 

class EchoFactory(protocol.ClientFactory): 
    def __init__(self,server_name): 
     self.server_name = server_name 

    def buildProtocol(self, addr): 
     client = EchoClient() 
     client.factory = self 
     return client 

    def clientConnectionFailed(self, connector, reason): 
     reactor.stop() 

    def clientConnectionLost(self, connector, reason): 
     time.sleep(10) 
     connector.connect() 

conn1 = EchoFactory('server1') 
conn2 = EchoFactory('server2') 

reactor.connectTCP("localhost",8000,conn1) 
reactor.connectTCP("localhost",8001,conn2) 

reactor.run() 

現在,當我運行程序我看到server1.log既有Connected to server1Connected to server2線,而server2.log只有Connected to server2

我該如何解決這個問題?謝謝。

回答

1

,你有這裏的問題是,log.startLogging,就是要 稱爲一次每個進程的壽命,打開一個日誌文件。如果你覺得 一下,如何被扭曲應該知道哪些日誌文件中的特定log.msg 呼籲應該去在你的榜樣?您沒有傳遞日誌文件或任何有關要使用哪一個的信息。

也有一些關於你的榜樣東西都使用非常 老式的扭曲的成語,所以我要去 徹底修改此示例以使用新的API扭曲:

  1. 而不是使用舊的和破壞的twisted.python.log模塊,我要 使用new logging hotnesstwisted.logger
  2. 而不是使用舊的和搗毀IReactorTCP.connectTCP,我要去 使用 Endpoints 具有許多優點。
  3. 而不是導入反應器,並直接運行它,我將使用 twisted.internet.task.react 讓我依靠全球反應器(這是 bad)。

也有幾件事情你做的這是總是在扭曲的一個壞主意 :

  1. 你不應該使用time.sleep()任何扭曲的程序,直到永遠。它會阻止整個反應堆的 ,這意味着Twisted 程序中的所有未完成任務(除了線程中的那些任務)都會在您等待時停止。 有異步API,如 deferLater, ,你可以用它來處理時間的流逝。
  2. 您不應該使用字符串格式將日誌消息放在一起。 twisted.logger使這是一個更容易一些,有更好的語法,但即使 twisted.python.log一直有一個在日誌結構化數據 消息的支持。
  3. 在幾個地方有兩個空格縮進。恥辱 :)。

我打算通過使用Twisted日誌系統來回答你的問題,但 發射日誌從您的連接只專用觀察員。究其原因 ,我做這個是它的有點棘手目的地爲全局日誌攔截日誌消息 和說服現有的全球記錄 基礎設施,它不應寫入主要日誌文件的消息。 這是通過設計:一旦設置日誌記錄,它通常用作捕獲所有導致錯誤的消息所必需的全部內容,即 。另一個潛在的 答案將是簡單地從每個連接打開一個文本文件,而不涉及Twisted的日誌記錄系統。

下面是如何做到這一點的例子:

import io 

from twisted.internet import protocol 
from twisted.logger import Logger, jsonFileLogObserver 

class EchoClient(protocol.Protocol): 
    log = Logger() 

    def connectionMade(self): 
     log = self.log 
     log.observer = jsonFileLogObserver(
      io.open(self.factory.server_name + ".json.log", "tw") 
     ) 
     self.log = log 

     self.log.info("Connected to {log_source.factory.server_name}") 

    def dataReceived(self, data): 
     self.log.info("server said: {data!r}", 
         data=data) 

    def connectionLost(self, reason): 
     self.log.info("Connection is lost: {reason}", 
         reason=reason) 

class EchoFactory(protocol.Factory): 
    protocol = EchoClient 
    def __init__(self, server_name): 
     self.server_name = server_name 

from twisted.internet.task import react 
from twisted.internet.endpoints import HostnameEndpoint 
from twisted.internet.defer import Deferred 

def main(reactor): 
    for portNumber in 8001, 8002: 
     endpoint = HostnameEndpoint(reactor, "localhost", portNumber) 
     endpoint.connect(
      EchoFactory("server_" + str(portNumber - 8000)) 
     ) 
    return Deferred() 

react(main) 

注意,在connectionMade,我們得到了Logger實例與self.log, 但由於類屬性EchoClient.log是一個描述符,它是創造一個 新實例每一次。爲確保我們的修改後的observer屬性狀態 持久存在,我們將self.log重新分配給生成的對象。

這將產生一些包含豐富結構化信息的日誌文件,但 可能有點難以讓人閱讀。如果你真的關心的是 字面文本日誌文件需要人們閱讀,而你不想做任何日誌分析,你可以使用textFileLogObserver而不是 jsonFileLogObserver;然而,通過一小段代碼,你可以得到兩個世界上最好的 。這裏有一個很短的程序,將讀到這裏產生的日誌文件 之一,併發出一個人可以閱讀或管道 到grep經典日誌文本:

import io 
from twisted.logger import eventsFromJSONLogFile, formatEventAsClassicLogText 

for event in eventsFromJSONLogFile(io.open("server_1.json.log", "rt")): 
    print(formatEventAsClassicLogText(event)) 
相關問題