2010-05-17 85 views
3

我有很多用Python 2.6編寫的腳本可以任意運行。我想要一箇中央腳本來收集輸出並將其顯示在單個日誌中。多個python腳本發送消息到一箇中央腳本

在理想情況下,將滿足這些要求:

  • 每個腳本發送其消息到相同的「接收器」用於顯示。
  • 如果第一個腳本嘗試發送消息時接收器未運行,則會啓動它。
  • 接收器也可以啓動並手動結束。 (儘管如果結束,如果另一個腳本嘗試發送消息,它將重新啓動。)
  • 腳本可以以任意順序運行,即使同時運行。
  • 運行於Windows。多平臺更好,但至少需要在Windows上工作。

我遇到了一些線索:

從這些作品中,我想我可以拼湊一些東西在一起。只是想知道是否有明顯的「正確」做法,或者如果我能從任何人的錯誤中學習。

+1

你看過logging.handlers.SocketHandler:http://docs.python.org/library/logging#sending-and-receiving-logging-events-across-a-network?它至少包含了你爲你描述的部分內容,並且是標準庫的一部分。 – 2010-05-18 00:08:22

+0

@丹這看起來很有用,你應該把它寫成答案。 ;) – Ipsquiggle 2010-05-18 00:26:44

回答

5

我會考慮使用logging.handlers.SocketHandler作爲消息傳遞的一部分,這聽起來像你有一個記錄類型的用例。

標準庫日誌記錄工具非常靈活,並且配置驅動,因此您應該能夠使其適應您的需求。

這不處理您的問題的自動重新啓動部分。對於UNIX,你可能只是使用pid文件和​​os.kill(pid, 0)來檢查它是否在運行,但我不知道它們在Windows世界中的等同物是什麼。

+0

這絕對看起來像*完全*我想要的消息發送。謝謝。 :)但是,它確實存在自動重新啓動的問題。我可能會剛剛開始一個更關注於此的新問題。 – Ipsquiggle 2010-05-25 23:39:52

+0

我不太瞭解Windows上的這些東西,'inetd'就是你在老派UNIX地區使用的東西。也許有一個Windows的等價物? – 2010-05-26 00:42:13

+0

如果它們無法連接到您指定的端口,您就只能從其他腳本內重新啓動接收器腳本... – 2010-05-26 01:07:00

1

我建了一個服務器使用Windows命名管道,使用下面的關鍵代碼:

def run(self): 
     # This is the main server loop for the Win32 platform 
     import win32pipe 
     import win32file 
     self.pipeHandle = win32pipe.CreateNamedPipe(
      '\\\\.\\pipe\\myapp_requests', 
      win32pipe.PIPE_ACCESS_DUPLEX, 
      win32pipe.PIPE_TYPE_BYTE | 
      win32pipe.PIPE_READMODE_BYTE | 
      win32pipe.PIPE_WAIT, 
      1, 
      4096, 
      4096, 
      10000, 
      None) 
     if self.pipeHandle == win32file.INVALID_HANDLE_VALUE: 
      print 'Failed to create named pipe %s!' % self.pipeName 
      print 'Exiting...' 
      sys.exit(1) 
     while True: 
      # Open file connection 
      win32pipe.ConnectNamedPipe(self.pipeHandle) 

      # Run the main message loop until it exits, usually because 
      # of a loss of communication on the pipe 
      try: 
       self.messageLoop() 
      except ServerKillSignal: 
       break 

      # Return the pipes to their disconnected condition and try again 
      try: win32pipe.DisconnectNamedPipe(self.pipeHandle) 
      except: pass 
     win32file.CloseHandle(self.pipeHandle) 
     print "Exiting server" 

的方法messageLoop()從管道中讀取數據,使用win32file.ReadFile(),直到win32file.error被拋出。然後它退出,允許run()重新啓動它。

在我的實現中,用戶不太可能擁有管理員訪問權限,因此這不能作爲系統服務啓動。相反,我編寫客戶端來檢查'\。\ pipe \ pyccf_requests'中是否存在管道。如果它不存在,那麼客戶端啓動一個新的服務器進程。

+0

這看起來很有用。這是你正在使用的圖書館嗎? http://starship.python.net/~skippy/win32/ – Ipsquiggle 2010-05-18 00:30:25

+1

是的,就是這樣。它被包含在ActiveState python發行版的一部分中,這正是我正在構建的版本: http://www.activestate.com/activepython/downloads – 2010-05-18 00:38:32

0

Dan Head的回答正是你想要的。

項目#2,「如果第一個腳本試圖發送消息時它沒有運行,它就會啓動」,可能不起作用。必須運行某些東西才能收到消息。我建議編寫一個在啓動時啓動的惡魔進程,並告訴Windows如果死掉就重新啓動它。

+0

感謝您的反饋意見。我正在權衡這與其他建議讓接收器佔用一個端口/管道,並且如果沒有找到它,就會產生它。對此有何想法? – Ipsquiggle 2010-05-25 23:38:49

+0

該解決方案很好。我建議在單個應用程序中可能會有太多「智能」。有一臺服務器,一個客戶端和一個腳本,在惡意程序崩潰時重新啓動它。重新啓動程序可以在任何服務器上運行。這樣每個部件都更簡單,因此更可靠。 – johntellsall 2010-05-27 05:10:38

相關問題