Max threads Python and how kill Thread? - python

I make daemon which creates N threads. N beetwen 1 to 500.
When thread end handling data it must die. When thread start it create log file and write to it. When it die - file should be remove. When threads started its check LOCK file. If file removed it should be die. But sometimes not. Why thread does not die immidiatly?
class HandlerWorker(threading.Thread):
q_reader = None
q_writer = None
q_cmd = None
id = ''
task_id = 0
def __init__(self,id,task_id,q_reader,q_writer,q_cmd):
'''
Constructor
'''
#print "Worker %d started" % int(id)
self.id = id
self.task_id = task_id
self.q_cmd = q_cmd
self.q_reader = q_reader
self.q_writer = q_writer
threading.Thread.__init__(self)
def __del__(self):
print "Destroy worker %d %d" % (int(self.task_id),int(self.id))
def isPid(self):
is_pid = True
try:
cfg = ConfigReader('config.json')
general = cfg.getGeneral()
pidfile = "%s%d" % (str(general['pids']),int(self.task_id))
f=open(pidfile,'r')
f.close()
except:
is_pid = False
return is_pid
def run(self):
'''
Handle email
'''
is_run = True
cfg = ConfigReader('config.json')
general = cfg.getGeneral()
logpath = str(general['pids'])+"../logs/%d_%d" % (int(self.task_id),int(self.id))
f = open(logpath,"w+")
while is_run:
if not self.q_reader.empty():
msg = self.q_reader.get()
# convert message
self.q_writer.put(msg)
log_str = "Date: %s Email:%s Status:%d\n" % (str(time.asctime()),str(msg),int(status))
f.write(log_str);
f.flush()
is_run = self.isPid()
time.sleep(1)
f.close()
try:
os.remove(logpath)
except:
print "Can't remove LOG file: %s" %logpath
print "Stop thread %d %d" % (int(self.task_id),int(self.id))

Related

Multithreading - XMLRPC server registering class objects as individual threads in Python 2.7.12

From the server side, I have prepared a python script where the following tasks are performed.
Task 1 => Acquiring data from the sensors
Task 2 => Setting a certain register in the robot control unit to 1 or 0 depending upon the acquired data from the sensors
To do the above-mentioned tasks, i implemented two individual threads. To perform task 1, i have defined the class "SensorEvaluationBoard(Thread)" and for performing task 2 i have defined the class "UR_RTDE(Thread)". For more details, please see the following python script from the server side.
Server side:
#!/usr/bin/env python
import time
from time import sleep
import sys
import string
import traceback
import logging
import socket
import struct
import copy
import xmlrpclib
# xmlrpclib.Marshaller.dispatch[type(0L)] = lambda _, v, w: w("<value><i8>%d</i8></value>" % v)
# xmlrpclib.dumps((2**63-1,))
xmlrpclib.Binary
from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler
import threading
from threading import Thread, Lock
# "https://www.universal-robots.com/articles/ur-articles/real-time-data-exchange-rtde-guide/"
import rtde.rtde as rtde
import rtde.rtde_config as rtde_config
# urHost = "127.0.0.1" # UR robot's IP address
# "https://www.universal-robots.com/articles/ur-articles/remote-control-via-tcpip/"
urPort = 30004 # Port number dedicated for UR robot's secondary interface
config_filename = 'control_loop_configuration.xml'
mutexFreedriveMode = Lock()
loadCycleOfSensor1, loadCycleOfSensor2, loadCycleOfSensor3 = "", "", ""
c1, c2, c3 = 0, 0, 0
cnt = 0
data = bytearray()
sensEvalBoard_ipAddr = "" # IP address of sensor evaluation board
sensEvalBoard_port = 0 # Port number of of sensor evaluation board
DEFAULT_TIMEOUT = 1
mutexSensVal = Lock()
sebSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # initializing the socket object
mutexSEBSocket = Lock()
def set_ipaddr(new_daemon_host):
global sensEvalBoard_ipAddr
sensEvalBoard_ipAddr = new_daemon_host
return sensEvalBoard_ipAddr
def get_ipaddr():
tmp = ""
if str(sensEvalBoard_ipAddr):
tmp = sensEvalBoard_ipAddr
else:
tmp = "No ip address set"
return tmp
def set_portnum(new_daemon_port):
global sensEvalBoard_port
sensEvalBoard_port = int (new_daemon_port)
return sensEvalBoard_port
def get_portnum():
tmp = 0
if sensEvalBoard_port != 0:
tmp = sensEvalBoard_port
else:
tmp = 0
return tmp
class ConnectionState:
DISCONNECTED = 0
CONNECTED = 1
STARTED = 2
PAUSED = 3
class SensorEvaluationBoardException(Exception):
def __init__(self, msg):
self.msg = msg
def __str__(self):
return repr(self.msg)
class SensorEvaluationBoard(Thread):
def __init__(self, hostname, port):
# Call the Thread class's init function
Thread.__init__(self)
self.__hostname = hostname
self.__port = port
self.__conn_state = ConnectionState.DISCONNECTED
self.__sock = None
logging.basicConfig(level=logging.DEBUG)
self.__logger = logging.getLogger(self.__class__.__name__)
# self.__streamHandler = logging.StreamHandler()
# self.__streamHandler.setLevel(logging.DEBUG)
# self.__formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
# self.__streamHandler.setFormatter(self.__formatter)
# self.__logger.addHandler(self.__streamHandler)
def connect(self):
global sebSocket
if self.__sock:
return
self.__buf = b''
try:
self.__sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.__sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.__sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
self.__sock.settimeout(DEFAULT_TIMEOUT)
self.__sock.connect((self.__hostname, self.__port))
self.__conn_state = ConnectionState.CONNECTED
sebSocket = copy.deepcopy(self.__sock)
except (socket.timeout, socket.error):
self.__sock = None
raise
def disconnect(self):
if self.__sock:
self.__sock.close()
self.__sock = None
self.__conn_state = ConnectionState.DISCONNECTED
def is_connected(self):
return self.__conn_state is not ConnectionState.DISCONNECTED
def get_connection_state(self):
return self.__conn_state
def send_input_data(self, data):
self.__sock.send(data)
def receive_output_data(self, input_data):
self.send_input_data(input_data)
self.__rcvData = self.__sock.recv(1024)
return self.__rcvData
def run(self):
global loadCycleOfSensor1, loadCycleOfSensor2, loadCycleOfSensor3
self.connect()
while True:
if self.is_connected:
# print("Socket => connection state: " + str(self.get_connection_state()) + " means CONNECTED")
self.__input_data = bytearray()
self.__input_data.append(0x1)
self.__rcvData = self.receive_output_data(self.__input_data)
self.__unpacker_string = 3*'I I I I I B B B B'
self.__unpacker = struct.Struct('<B '+ self.__unpacker_string)
self.__unpacked = self.__unpacker.unpack(self.__rcvData)
# print("Slave 1: "+ repr(self.__unpacked[1:10]))
# print("Slave 2: "+ repr(self.__unpacked[10:19]))
# print("Slave 3: "+ repr(self.__unpacked[19:28]))
mutexSensVal.acquire()
loadCycleOfSensor1 = str(self.__unpacked[1])
loadCycleOfSensor2 = str(self.__unpacked[12])
loadCycleOfSensor3 = str(self.__unpacked[20])
# print("Load cycle of sensors 1, 2 and 3: ["+ loadCycleOfSensor1 + ", " + loadCycleOfSensor2 + ", " + loadCycleOfSensor3 + "]")
mutexSensVal.release()
sleep(0.1)
else:
print("Socket => connection state: " + str(self.get_connection_state()) + " means DISCONNECTED")
class UR_RTDE(Thread):
def __init__(self, host, port, config_filename):
# Call the Thread class's init function
Thread.__init__(self)
self.__host = host
self.__port = port
self.__config_filename = config_filename
logging.basicConfig(level=logging.DEBUG)
self.__logger = logging.getLogger(self.__class__.__name__)
# self.__streamHandler = logging.StreamHandler()
# self.__streamHandler.setLevel(logging.INFO)
# self.__formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
# self.__streamHandler.setFormatter(self.__formatter)
# self.__logger.addHandler(self.__streamHandler)
self.__con = None
self._rtde_ok = False
self._recept_ok = False
self._dataAccessConfig = Lock()
self.__keep_running = True
def init_rtde(self):
self.__logger.debug("init_rtde")
if not self._rtde_ok :
if self.__con is None:
self.connect_rtde()
if not self._recept_ok:
self.init_conf()
self.send_conf_to_robot()
self.start_communication()
self._rtde_ok = True
def connect_rtde(self):
self.__logger.debug("connect_rtde")
try:
self.__con = rtde.RTDE(self.__host, self.__port)
self.__con.connect()
except socket.timeout as e:
self.__logger.error("failed to connect with robot", exc_info=True)
self.__controller_info = None
self.__con = None
self.__controller_info = self.__con.get_controller_version()
self.__logger.info("connected with UR established")
self.__logger.info(self.__controller_info)
return True
def disconnect_rtde(self):
self.__con.send_pause()
self.__con.disconnect()
self.__logger.debug("disconnect_rtde")
def init_conf(self):
self.__logger.debug("init_conf")
with self._dataAccessConfig:
self._conf = rtde_config.ConfigFile(self.__config_filename)
self._state_names, self._state_types = self._conf.get_recipe('state')
self._set_freedrive_name, self._set_freedrive_type = self._conf.get_recipe('set_freedrive')
def send_conf_to_robot(self):
self.__logger.debug("send_conf_to_robot")
print("in send conf")
try:
self.__con.send_output_setup(self._state_names, self._state_types)
self.__set_freedrive = self.__con.send_input_setup(self._set_freedrive_name, self._set_freedrive_type)
self.__set_freedrive.__dict__[b"input_bit_register_64"] = 0
self._recept_ok = True
except Exception as e:
self.__set_freedrive = None
self.__logger.error("rtde recepts error", exc_info=True)
self._recept_ok = False
def start_communication(self):
self.__logger.debug("start_communication")
if not self.__con.is_connected():
self.__logger.warning("no connection established")
if not self.__con.send_start():
self.__logger.warning("starting data_sync failed")
sys.exit()
self.__logger.info("started communication")
return True
def run(self):
global loadCycleOfSensor1, loadCycleOfSensor2, loadCycleOfSensor3
global c1, c2, c3
lowerThr_loadCycleOfSensor1, upperThr_loadCycleOfSensor1 = 400, 700
lowerThr_loadCycleOfSensor2, upperThr_loadCycleOfSensor2 = 100, 400
lowerThr_loadCycleOfSensor3, upperThr_loadCycleOfSensor3 = 200, 425
lTh_c1 = lowerThr_loadCycleOfSensor1
uTh_c1 = upperThr_loadCycleOfSensor1
lTh_c2 = lowerThr_loadCycleOfSensor2
uTh_c2 = upperThr_loadCycleOfSensor2
lTh_c3 = lowerThr_loadCycleOfSensor3
uTh_c3 = upperThr_loadCycleOfSensor3
self.init_rtde()
# Set the 'input_bit_register_64' to 0 by default
self.__set_freedrive.__dict__[b"input_bit_register_64"] = 0
if self.__con.is_connected():
while self.__keep_running:
# receive the current state
self.__state = self.__con.receive()
if self.__state is None:
break
mutexSensVal.acquire()
c1 = int (loadCycleOfSensor1)
self.__logger.info("Loading cycle of CapSen1 is " + str(c1))
c2 = int (loadCycleOfSensor2)
self.__logger.info("Loading cycle of CapSen2 is " + str(c2))
c3 = int (loadCycleOfSensor3)
self.__logger.info("Loading cycle of CapSen3 is " + str(c3))
mutexSensVal.release()
mutexFreedriveMode.acquire()
# input_bit_register_64 refers to "general purpose input register 64"
# if "general purpose input register 64" variable is set to 1 => Freedrive mode is activated
if ((lTh_c1 < c1 < uTh_c1) and (lTh_c2 < c2 < uTh_c2)):
self.__set_freedrive.__dict__[b"input_bit_register_64"] = 1
self.__logger.info("Capacitive sensors 1 and 2 are touched by the human operator, Freedrive mode activated")
elif ((lTh_c2 < c2 < uTh_c2) and (lTh_c3 < c3 < uTh_c3)):
self.__set_freedrive.__dict__[b"input_bit_register_64"] = 1
self.__logger.info("Capacitive sensors 2 and 3 are touched by the human operator, Freedrive mode activated")
elif ((lTh_c3 < c3 < uTh_c3) and (lTh_c1 < c1 < uTh_c1)):
self.__set_freedrive.__dict__[b"input_bit_register_64"] = 1
self.__logger.info("Capacitive sensors 1 and 3 are touched by the human operator, Freedrive mode activated")
else:
self.__set_freedrive.__dict__[b"input_bit_register_64"] = 0
self.__logger.info("No two capacitive sensors are touched by the human operator, Freedrive mode deactivated")
self.__con.send(self.__set_freedrive)
mutexFreedriveMode.release()
sleep(0.1)
self.disconnect_rtde()
def main():
try:
# threadevent = threading.Event()
# Create an object of Thread
th_sensevalboard = SensorEvaluationBoard(sensEvalBoard_ipAddr, sensEvalBoard_port)
# start the SensorEvaluationBoard thread
th_sensevalboard.start()
sleep(1)
# Create an object of Thread
th_rtde = UR_RTDE(urHost, urPort, config_filename)
# start the RTDE thread
th_rtde.start()
return "SensorEvaluationBoard and RTDE threads has started..."
except KeyboardInterrupt:
print("Terminating communication with the sensor evaluation board... ")
th_sensevalboard.disconnect()
print("Socket => connection state: " + str(th_sensevalboard.get_connection_state()) + " means DISCONNECTED")
th_sensevalboard.join()
print ("SensorEvaluationBoard thread successfully closed")
print("Terminating communication with the RTDE server... ")
th_rtde.disconnect()
th_rtde.join()
print ("RTDE thread successfully closed")
return "SensorEvaluationBoard and RTDE threads has stopped..."
sys.stdout.write("CapSens daemon started")
sys.stderr.write("CapSens daemon started with caught exception")
# server_addr = ("127.0.0.1", 40405)
# server = SimpleXMLRPCServer(server_addr, SimpleXMLRPCRequestHandler, allow_none=True)
server = SimpleXMLRPCServer(("127.0.0.1", 40405), allow_none=True)
server.register_function(set_ipaddr, "set_ipaddr")
server.register_function(get_ipaddr, "get_ipaddr")
server.register_function(set_portnum, "set_portnum")
server.register_function(get_portnum, "get_portnum")
server.register_instance(UR_RTDE(urHost, urPort, config_filename), allow_dotted_names=True)
server.register_instance(SensorEvaluationBoard(sensEvalBoard_ipAddr, sensEvalBoard_port), allow_dotted_names=True)
server.register_function(main, "main")
server.serve_forever()
In the main() function of the above-mentioned python script, i initialize the two threads 'th_sensevalboard' and 'th_rtde' and start them one after the other. After the main() function, i tried to register the class objects which are individual threads as instances to an XMLRPC server. I am not sure, if this is the right way to do it.
Can anyone please have a look at the above-mentioned python script and tell me if the way in which i register multiple class objects which which are individual threads as instances to an XMLRPC server is proper or not? If it is not the proper way, can you please give me your suggestions.
Best Regards

Handling kill events for python multiprocessing processes

For a program that should run both on Linux and Windows (python 2.7), I'm trying to update values of a given object using multiprocessing.Process (while the main program is running, I'm calling the update class by a separate process).
Sometimes it takes too long before my object is updated, so I want to be able to kill my update process, and to continue with the main program. "Too long" is not strictly defined here, but rather a subjective perception of the user.
For a single queue (as in the MyFancyClass example in http://pymotw.com/2/multiprocessing/communication.html) I can kill the update process and the main program continues as I want.
However, when I make a second queue to retrieve the updated object, ending the update process does not allow me to continue in the main program.
What I have so far is:
import multiprocessing
import time, os
class NewParallelProcess(multiprocessing.Process):
def __init__(self, taskQueue, resultQueue, processName):
multiprocessing.Process.__init__(self)
self.taskQueue = taskQueue
self.resultQueue = resultQueue
self.processName = processName
def run(self):
print "pid %s of process that could be killed" % os.getpid()
while True:
next_task = self.taskQueue.get()
if next_task is None:
# poison pill for terminate
print "%s: exiting" % self.processName
self.taskQueue.task_done()
break
print "%s: %s" % (self.processName, next_task)
answer = next_task()
self.taskQueue.task_done()
self.resultQueue.put(answer)
return
class OldObject(object):
def __init__(self):
self.accurate = "OldValue"
self.otherValue = "SomeOtherValue"
class UpdateObject(dict):
def __init__(self, objectToUpdate):
self.objectToUpdate = objectToUpdate
def __call__(self):
returnDict = {}
returnDict["update"] = self.updateValue("NewValue")
return returnDict
def __str__(self):
return "update starting"
def updateValue(self, updatedValue):
for i in range(5):
time.sleep(1) # updating my object - time consuming with possible pid kill
print "working... (pid=%s)" % os.getpid()
self.objectToUpdate.accurate = updatedValue
return self.objectToUpdate
if __name__ == '__main__':
taskQueue = multiprocessing.JoinableQueue()
resultQueue = multiprocessing.Queue()
newProcess = NewParallelProcess(taskQueue, resultQueue, processName="updateMyObject")
newProcess.start()
myObject = OldObject()
taskQueue.put(UpdateObject(myObject))
# poison pill for NewParallelProcess loop and wait to finish
taskQueue.put(None)
taskQueue.join()
# get back results
results = resultQueue.get()
print "Values have been updated"
print "---> %s became %s" % (myObject.accurate, results["update"].accurate)
Any suggestions on how to kill the newProcess and to continue in the main program?
Well, made some modifications, and this does what I want. Not sure whether it is the most efficient, so any improvements are always welcome :)
import multiprocessing
import time, os
class NewParallelProcess(multiprocessing.Process):
def __init__(self, taskQueue, resultQueue, processName):
multiprocessing.Process.__init__(self)
self.taskQueue = taskQueue
self.resultQueue = resultQueue
self.name = processName
def run(self):
print "Process %s (pid = %s) added to the list of running processes" % (self.name, self.pid)
next_task = self.taskQueue.get()
self.taskQueue.task_done()
self.resultQueue.put(next_task())
return
class OldObject(object):
def __init__(self):
self.accurate = "OldValue"
self.otherValue = "SomeOtherValue"
class UpdateObject(dict):
def __init__(self, objectToUpdate, valueToUpdate):
self.objectToUpdate = objectToUpdate
self.valueToUpdate = valueToUpdate
def __call__(self):
returnDict = {}
returnDict["update"] = self.updateValue(self.valueToUpdate)
return returnDict
def updateValue(self, updatedValue):
for i in range(5):
time.sleep(1) # updating my object - time consuming with possible pid kill
print "working... (pid=%s)" % os.getpid()
self.objectToUpdate.accurate = updatedValue
return self.objectToUpdate
if __name__ == '__main__':
# queue for single process
taskQueue = multiprocessing.JoinableQueue()
resultQueue = multiprocessing.Queue()
newProcess = NewParallelProcess(taskQueue, resultQueue, processName="updateMyObject")
newProcess.start()
myObject = OldObject()
taskQueue.put(UpdateObject(myObject, "NewValue"))
while True:
# check if newProcess is still alive
time.sleep(5)
if newProcess.is_alive() is False:
print "Process %s (pid = %s) is not running any more (exit code = %s)" % (newProcess.name, newProcess.pid, newProcess.exitcode)
break
if newProcess.exitcode == 0:
print "ALL OK"
taskQueue.join()
# get back results
print "NOT KILLED"
results = resultQueue.get()
print "Values have been updated"
print "---> %s became %s" % (myObject.accurate, results["update"].accurate)
elif newProcess.exitcode == 1:
print "ended with error in function"
print "KILLED"
for i in range(5):
time.sleep(1)
print "i continue"
elif newProcess.exitcode == -15 or newProcess.exitcode == -9:
print "ended with kill signal %s" % newProcess.exitcode
print "KILLED"
for i in range(5):
time.sleep(1)
print "i continue"
else:
print "no idea what happened"
print "KILLED"
for i in range(5):
time.sleep(1)
print "i continue"

python stop threading that are running

I know this question is asked a lot of time but i am still like to know.
def startMonitor(self,event):
selectedInterface = self.interfaces_cblist.GetValue()
Publisher().sendMessage(("test"),selectedInterface)
self.Close()
selectInterfaceStr = str(selectedInterface)
if len(selectedInterface) == 0:
noSelect_error = wx.MessageDialog(None,"Please select an interface","",wx.OK|wx.ICON_ERROR)
noSelect_error.ShowModal()
else:
monitorStarted = wx.MessageDialog(None,"Monitor on %s started"%selectInterfaceStr,"",wx.OK|wx.ICON_ERROR)
monitorStarted.ShowModal()
self.monitorInterface_button.Disable()
thread.start_new_thread(self.camtableDetection,(selectInterfaceStr,))
thread.start_new_thread(self.dhcpexhaustion,(selectInterfaceStr,))
how can i stop the threading?
You can have a stop method that assigns to a variable such as self.abort. Than, in the function you are threading, you should check for this variable regularly and stop the function(with return or something similar). Here's an example class that uses this technique for stopping the thread.
class PymineLogger:
def __init__(self):
self.file = open('server.log', 'a')
self.abort = False
self.log_queue = Queue.Queue()
threading.Thread(target=self.process_queue, args=()).start()
def error(self, i):
line = u'[%s] [ERROR] %s' % (str(time.time()), i)
self.log_queue.put(line)
def info(self, i):
line = u'[%s] [INFO] %s' % (str(time.time()), i)
self.log_queue.put(line)
def process_queue(self):
while not self.abort:
try:
log_line = self.log_queue.get(timeout=1)
print log_line
self.file.write("%s\n" % log_line)
self.file.flush()
except Queue.Empty:
pass
def stop(self):
self.abort = True
The stop method assigns the variable self.abort, which gets regularly checked by the thread.
Class source: pymine2 project

How to get the status of spawn process in twisted python?

I want to trigger many long running processes continiously. And, based on the status returned of each process executed, I need to perform other tasks. In the below example, I'm able to spawn processes, but I'm not able to capture/get the details of the spawn processes execution status returned to mail loop(i.e in CmdProtocol class).
I'm new to this twisted python concepts - Can someone help me here?
import sys
from twisted.internet.protocol import ServerFactory, ProcessProtocol
from twisted.protocols.basic import LineReceiver
from twisted.internet import reactor
from twisted.internet import protocol
import os
import signal
class MyPP(protocol.ProcessProtocol):
def __init__(self):
self.parent_id = os.getpid()
def connectionMade(self):
print "connectionMade!"
print "Parent id = %s" % self.parent_id
print "Child process id = %s" % self.transport.pid
def outReceived(self, data):
print "out", data
def errReceived(self, data):
print "error", data
def inConnectionLost(self):
print "inConnectionLost! stdin is closed! (we probably did it)"
print "Parent id = %s" % self.parent_id
print "Child process id closes STDIN= %s" % self.transport.pid
def outConnectionLost(self):
print "outConnectionLost! The child closed their stdout!"
print "Parent id = %s" % self.parent_id
print "Child process id closes STDOUT = %s" % self.transport.pid
def errConnectionLost(self):
print "errConnectionLost! The child closed their stderr."
print "Parent id = %s" % self.parent_id
print "Child process id closes ERRCONN = %s" % self.transport.pid
def processExited(self, reason):
print "processExited %s, status %d" % (self.transport.pid, reason.value.exitCode,)
def processEnded(self, reason):
print "%s processEnded, status %d" % (self.transport.pid, reason.value.exitCode,)
print "quitting"
class CmdProtocol(LineReceiver):
delimiter = '\n'
def connectionMade(self):
self.client_ip = self.transport.getPeer()
print "Client connection from %s" % self.client_ip
def processcmd(self):
pp = MyPP()
cmd = ['c:\Python27\python.exe', '-u', 'print_hi.py']
print "Calling processcmd - <%s>" % cmd
reactor.spawnProcess(pp, cmd[0], cmd[1:])
def connectionLost(self, reason):
print "Lost client connection. Reason: %s" % reason
def lineReceived(self, line):
if not line: return
# Parse the command
print 'Cmd received from %s : %s' % (self.client_ip, line)
commandParts = line.split()
if len(commandParts) > 0:
command = commandParts[0].lower()
args = commandParts[1:]
try:
print "Command received : <%s>" % command
method = getattr(self, command)
except AttributeError, e:
self.sendLine('Error: no such command.')
else:
try:
res = method()
print "Returned status:%s" % res
self.sendLine('Command executed successfully.')
except Exception, e:
self.sendLine('Error: ' + str(e))
def do_kill(self, pid):
"""kill: Kill a process (PID)"""
print 'Killing pid:%s' % pid
res = os.kill(int(pid), signal.SIGTERM)
print "Kill Status %s" % res
class MyFactory(ServerFactory):
protocol = CmdProtocol
def __init__(self):
print "Factory called"
reactor.listenTCP(8000, MyFactory())
reactor.run()
This is actually a very basic Python data structures question. You just need to refer to an instance of CmdProtocol from an instance of MyPP. Since CmdProtocol is what constructs MyPP in the first place, this is easy. Just change the construction of MyPP to look like this:
def processcmd(self):
pp = MyPP(self)
and then MyPP.__init__ to look like this:
def __init__(self, cmd_protocol):
self.parent_id = os.getpid()
self.cmd_protocol = cmd_protocol
Then, in any method on MyPP, you can access the relevant CmdProtocol instance with self.cmd_protocol.

Socket in python will only send data it receives

I must be missing something in the code. I've rewritten an 'echo server' example to do a bit more when it receives something.
This is how it currently looks:
#!/usr/bin/env python
import select
import socket
import sys
import threading
import time
import Queue
globuser = {}
queue = Queue.Queue()
class Server:
def __init__(self):
self.host = ''
self.port = 2000
self.backlog = 5
self.size = 1024
self.server = None
self.threads = []
def open_socket(self):
try:
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server.bind((self.host,self.port))
self.server.listen(5)
except socket.error, (value,message):
if self.server:
self.server.close()
print "Could not open socket: " + message
sys.exit(1)
def run(self):
self.open_socket()
input = [self.server,sys.stdin]
running = 1
while running:
inputready,outputready,exceptready = select.select(input,[],[])
for s in inputready:
if s == self.server:
# handle the server socket
c = Client(self.server.accept(), queue)
c.start()
self.threads.append(c)
elif s == sys.stdin:
# handle standard input
junk = sys.stdin.readline()
running = 0
# close all threads
self.server.close()
for c in self.threads:
c.join()
class Client(threading.Thread):
initialized=0
def __init__(self,(client,address), queue):
threading.Thread.__init__(self)
self.client = client
self.address = address
self.size = 1024
self.queue = queue
self.threads = []
global globuser
print 'Client thread created!'
def run(self):
running = 1
while running:
print 'While running client'
data = self.client.recv(self.size)
print 'Dit we receive data?'
if data:
print 'Data received!'
print 'Fetching data from socket: ',
if data[0] == 'I':
print 'Initializing user: ' + data
user = {'uid': data[1:6] ,'x': data[6:9], 'y': data[9:12]}
globuser[user['uid']] = user
print globuser
initialized=1
m=updateClient(user['uid'], queue)
m.start()
self.threads.append(m)
self.client.send('Beginning - Initialized'+';')
elif data[0] == 'A':
print 'Client has received previous data: ' + data
#On deactivation, nothing works.
self.client.send(data+';')
#print 'Client Data sent: ' + data
else:
print 'Closing'
self.client.close()
running = 0
if self.queue.empty():
print 'Queue is empty'
else:
print 'Queue has information: ',
data2 = self.queue.get(1, 1)
isdata2 = 1
if data2 == 'Exit':
running = 0
print 'Client is being closed'
self.client.close()
if isdata2 == 1:
print 'Sending data to client: ' + data2,
self.client.send(data2)
self.queue.task_done()
isdata2 = 0
time.sleep(1)
class updateClient(threading.Thread):
def __init__(self,uid, queue):
threading.Thread.__init__(self)
self.uid = uid
self.queue = queue
global globuser
print 'updateClient thread started!'
def run(self):
running = 20
test=0
while running > 0:
test = test + 1
self.queue.put('Test Queue Data #' + str(test))
running = running - 1
time.sleep(1)
print 'Updateclient has stopped'
if __name__ == "__main__":
s = Server()
s.run()
This runs fine, although it's kind of silly to keep sending the same data back again along with other data.
In the middle of the code you'll see
#On deactivation, nothing works.
self.client.send(data+';')
#print 'Client Data sent: ' + data
When I DO deactive the self.client.send(data+';') or change it into self.client.send('something else;') it does not work! And the client receives nothing.
Is there something special about the "data" variable? Do I need to format the string in some way?
Here's a cleaned-up, functional version of your code! I tested it myself, though I didn't write unit tests.
There were some syntax errors and other miscellaneous problems with the
original code, so I took some liberties. I'm assuming that the protocol is
framed by using ; as a delimiter, since a ; is sent at the end of every
message to the client, though no framing was being done in the original code.
from twisted.internet import reactor, protocol, task
from twisted.protocols import basic
from twisted.python import log
import sys
class ServerProtocol(basic.LineOnlyReceiver):
delimiter = ';'
def lineReceived(self, line):
if line.startswith('I'):
user = dict(uid=line[1:6], x=line[6:9], y=line[9:12])
self.factory.users[user['uid']] = user
log.msg(repr(self.factory.users))
self.startUpdateClient()
self.sendLine('Beginning - Initialized')
elif line.startswith('A'):
self.sendLine(line)
else:
self.transport.loseConnection()
def _updateClient(self):
if self._running == 0:
self._looper.stop()
return
self._running -= 1
self._test += 1
self.sendLine('Test Queue Data #%d' % (self._test,))
def startUpdateClient(self):
self._running, self._test = 20, 0
self._looper = task.LoopingCall(self._updateClient)
self._looper.start(1, now=False)
class Server(protocol.ServerFactory):
protocol = ServerProtocol
def __init__(self):
self.users = {}
if __name__ == '__main__':
log.startLogging(sys.stderr)
reactor.listenTCP(2000, Server())
reactor.run()

Categories