2011-07-11 140 views
0

快速的問題,我是從來沒有肯定是可能的:3不斷運行python腳本,通過終端調用函數

我有一個python腳本,連接到服務器,並保持連接直到我要麼斷開網絡腳本或者它踢我(它通常不應該),它不斷地接收數據和做其他任務。

我很好奇,腳本運行時是否有可能觸發腳本中的函數?在腳本運行的時候說,如果我有將數據發送到服務器的衝動,我可以輸入它並將它發送到處理該數據的函數?

不太確定是否有可能,因爲我從來沒有嘗試甚至沒有看到它完成。如果有幫助,我在Ubuntu Linux上運行終端上的腳本。

回答

0

沒有更多的細節,我只能爲您提供一般的想法。爲了一次執行兩件事(從服務器下載並等待數據發送),您將需要使用多個線程或進程。有一個教程,其中包含多個線程here的一些示例。如果您使用多個進程,則將使用multiprocessing程序包。

無論使用哪種解決方案,您都需要一個類似的設置。其餘部分我將使用術語線程,但如果使用多個進程,則可以輕鬆地將其替換爲進程。你可能會(至少)有一個線程來發送和接收數據(這可能是兩個線程)和一個單獨的線程來等待發送的東西。這是the producer/consumer problem的簡化示例。等待命令/數據的線程將是一個簡單的輸入循環,產生數據發送,而發送數據的線程將數據發送到服務器時會消耗

+0

如果需要,我可以共享代碼,但這聽起來正是我想要的。基本上,它幾乎是一個(授權的)機器人,它通過TCPConnection連接到服務器並穩定地接收和發送數據。我試圖做的是在一切正在運行的情況下,能夠調用其中一個函數,並在不中斷程序的情況下將數據發送到該函數。例如,機器人可能有一些硬編碼的數據來響應服務器發送的內容,但是如果我希望能夠發送一些自定義的內容(比如消息到遊戲聊天)。 – WeaponsTheyFear

+1

您還可以使用單線程異步事件循環更簡單地執行這些類型的IO綁定多路複用。像Twisted框架可以使用,它可能已經支持這個內置的。 – Keith

0

將您的服務器內容粘貼到另一個線程中(調查threading模塊),並使用主線程通過raw_input/input與用戶交互。

1

解決此類問題的常用「UNIX方式」是套接字和標準輸入文件描述符上的pollselect。然後在stdin文件描述符上的'IN'事件上的套接字和終端輸入上處理網絡輸入。

這不能移植到Windows(很糟糕),但這是在類UNIX系統上最自然的方式。而且你沒有得到線程所帶來的所有問題(因爲它們經常需要使用Python進行輪詢,否則它們會'不可驅動')。

1

gevent看看:

GEVENT是使用 greenlet提供有關 libevent的事件循環頂部的高層次的同步API基於協同程序的Python網絡庫。

and gevent.socket

1

Jacek Konieczny的解決方案非常簡單。如果你想要更靈活的消息傳遞,請考慮ZeroMQ。這使您可以輕鬆地在主程序周圍創建各種消息解決方案。使用一個線程,你的主要項目將是這個樣子:

#!/usr/bin/env python 

import zmq 
from time import sleep 

CTX = zmq.Context() 

incoming = CTX.socket(zmq.PULL) 
incoming.bind("tcp://127.0.0.1:3000") 

outgoing = CTX.socket(zmq.PUB) 
outgoing.bind("tcp://127.0.0.1:3001") 

# Poller for the incoming messages 
poller = zmq.Poller() 
poller.register(incoming, zmq.POLLIN) 

def main(): 
    while True: 
     # Do things on the network 
     print("[Did things on the network]") 
     # Send messages if you want 
     outgoing.send("Important message") 
     # Poll for incoming messages 
     socks = dict(poller.poll(zmq.NOBLOCK)) 
     if incoming in socks and socks[incoming] == zmq.POLLIN: 
      message = incoming.recv() 
      # Handle message 
      print("[Handled message '%s']" % message) 

     sleep(1) # Only for this dummy program 

if __name__ == "__main__": 
    main() 

你會再編寫一個客戶端(在具有ZeroMQ綁定任何語言)是推動和預訂來自主程序的消息。示例性推:

#!/usr/bin/env python 

import zmq 

CTX = zmq.Context() 

pusher = CTX.socket(zmq.PUSH) 
pusher.connect("tcp://127.0.0.1:3000") 

def main(): 
    pusher.send("Message to main program") 

if __name__ == "__main__": 
    main() 

例如用戶:

#!/usr/bin/env python 

import zmq 

CTX = zmq.Context() 

subscriber = CTX.socket(zmq.SUB) 
subscriber.connect("tcp://127.0.0.1:3001") 
subscriber.setsockopt(zmq.SUBSCRIBE, "") 

def main(): 
    while True: 
     msg = subscriber.recv() 
     print("[Received message] %s" % msg) 

if __name__ == "__main__": 
    main() 

這聽起來像是你將要推動和用戶程序合二爲一。如果您決定使用ZeroMQ,請看the excellent user guide

你當然也可以使用ZeroMQ與多線程或進程(只是要小心不要在線程之間共享各個ZeroMQ套接字)。

相關問題