At the moment i am writing a syslog client that will send messages to a remote syslog server. So far this is working pretty ok but i am running into the following problem.
When the syslog server goes down for some reason i need to catch this so the program will stop sending syslog messages and we can investigate the problem.
Unfortunately, the program continues running and doesn't see that the TCP socket is closed and raise an exception.
I only receive a traceback in my terminal:
--- Logging error --- Traceback (most recent call last):
File "C:\Users\Administrator\AppData\Local\Programs\Python\Python37\lib\logging\handlers.py", line 941, in emit
self.socket.sendall(msg) ConnectionAbortedError: [WinError 10053] Call stack:
File "c:\Users\Administrator\.vscode\extensions\ms-python.python-2018.12.1\pythonFiles\ptvsd_launcher.py", line 45, in <module>
main(ptvsdArgs)
File "c:\Users\Administrator\.vscode\extensions\ms-python.python-2018.12.1\pythonFiles\lib\python\ptvsd\__main__.py", line 265, in main
wait=args.wait)
File "c:\Users\Administrator\.vscode\extensions\ms-python.python-2018.12.1\pythonFiles\lib\python\ptvsd\__main__.py", line 258, in handle_args
debug_main(addr, name, kind, *extra, **kwargs)
File "c:\Users\Administrator\.vscode\extensions\ms-python.python-2018.12.1\pythonFiles\lib\python\ptvsd\_local.py", line 45, in debug_main
run_file(address, name, *extra, **kwargs)
File "c:\Users\Administrator\.vscode\extensions\ms-python.python-2018.12.1\pythonFiles\lib\python\ptvsd\_local.py", line 79, in run_file
run(argv, addr, **kwargs)
File "c:\Users\Administrator\.vscode\extensions\ms-python.python-2018.12.1\pythonFiles\lib\python\ptvsd\_local.py", line 140, in _run
_pydevd.main()
File "c:\Users\Administrator\.vscode\extensions\ms-python.python-2018.12.1\pythonFiles\lib\python\ptvsd\_vendored\pydevd\pydevd.py", line 1925, in main
debugger.connect(host, port)
File "c:\Users\Administrator\.vscode\extensions\ms-python.python-2018.12.1\pythonFiles\lib\python\ptvsd\_vendored\pydevd\pydevd.py", line 1283, in run
return self._exec(is_module, entry_point_fn, module_name, file, globals, locals)
File "c:\Users\Administrator\.vscode\extensions\ms-python.python-2018.12.1\pythonFiles\lib\python\ptvsd\_vendored\pydevd\pydevd.py", line 1290, in _exec
pydev_imports.execfile(file, globals, locals) # execute the script
File "c:\Users\Administrator\.vscode\extensions\ms-python.python-2018.12.1\pythonFiles\lib\python\ptvsd\_vendored\pydevd\_pydev_imps\_pydev_execfile.py", line 25, in execfile
exec(compile(contents+"\n", file, 'exec'), glob, loc)
File "c:\Users\Administrator\OneDrive\Documents\Python Scripts\testlogger.py", line 71, in <module>
my_logger.info(i) Message: 'test4' Arguments: ()
Relevant code:
my_logger = logging.getLogger('MyLogger')
my_logger.setLevel(logging.ERROR)
my_logger.setLevel(logging.INFO)
my_logger.setLevel(logging.DEBUG)
try:
handler = logging.handlers.SysLogHandler(('IP ADDRESS HOST', 514), socktype=socket.SOCK_STREAM)
my_logger.addHandler(handler)
except Exception as e:
print (e)
list1 = ['test','test2','test3','test4','test5','test6','test7','test8']
for i in list1:
try:
my_logger.info(i) #here i expected that an exception would be raised when the TCP socket is not alive anymore
except Exception as e:
print (e)
How can i make sure that the program stops and i can do the appropriate exception handling?
Thanks!
The default behavior of the SysLogHandler class (and all the ones who are using TCP) is to retry a connection, this is explained in the docs of the createSocket() method:
Tries to create a socket; on failure, uses an exponential back-off
algorithm. On initial failure, the handler will drop the message it
was trying to send. When subsequent messages are handled by the same
instance, it will not try connecting until some time has passed. The
default parameters are such that the initial delay is one second, and
if after that delay the connection still can’t be made, the handler
will double the delay each time up to a maximum of 30 seconds.
This behaviour is controlled by the following handler attributes:
retryStart (initial delay, defaulting to 1.0 seconds).
retryFactor (multiplier, defaulting to 2.0).
retryMax (maximum delay, defaulting to 30.0 seconds).
As it doesn't seem to have an option for the behavior of "not retrying" which you seem to want, so if you really want that you can create your own handler by subclassing it and overriding the createSocket() method with something like:
class MySysLogHandler(logging.handlers.SysLogHandler):
def createSocket(self):
try:
self.sock = self.makeSocket()
except OSError:
# do your own error handling here ...
You can dig a bit more by looking at the source code of createSocket() in CPython Github repo (beware, this is from master branch and might not be the exact version of Python you're using)
I switched to another solution and stopped using the SyslogHandler class.
I now use the following class were i wrote my own syslog sender through a socket.
class Syslog:
def __init__(self,host="localhost",port=514,facility=Facility.DAEMON):
self.host = host
self.port = port
self.facility = facility
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def connect(self):
try:
self.socket.connect((self.host, self.port))
except Exception as e:
print("failed setting up connection")
def send(self, message,level):
data = "<%d>%s" % (level + self.facility*8, message + "\n")
try:
self.socket.sendall(data.encode('utf-8'))
except Exception as e:
print("send failed")
#if __name__ == '__main__':
syslog1 = Syslog(host='HOSTIPADDRESS-NAME')
syslog1.connect()
messages = ["test1","test2","test3","test4","test5","test6","test7"]
for message in messages:
syslog1.send(message,Level.WARNING)
This is working quite well and runs into an exception when the syslog server goes down unexpectedly. The only problem now i discovered while debugging is the following:
When i shut down the syslog server it throws not immediatly an exception when i try to send a message.
Please see example below:
1.) the syslog server is started, i send the first message "test1" from the for loop, successfull.
2.) i shutdown the syslog server, now i send the second message "test2" from the for loop. Nothing happens, no exception!
3.) i send the third message "test3", now an exception is thrown.
How is this possible?
Related
Hello I managed to get locust to work with graphite with the following code:
class MyLocust(HttpUser):
tasks = [MyTask]
sock = None
def exit_handler(self):
self.sock.shutdown(socket.SHUT_RDWR)
self.sock.close()
def hook_request_success(self, request_type, name, response_time, response_length):
# print(response_time)
message="%s %d %d\n" % ("client." + name.replace('.', '-'), response_time, time.time())
self.sock.send(message.encode())
def hook_request_fail(self, request_type, name, response_time, exception):
self.request_fail_stats.append([name, request_type, response_time, exception])
def __init__(self, parent):
super().__init__(parent)
self.sock = socket.socket()
self.sock.connect( ("192.168.XX.YYYY", 2003) )
events.request_success.add_listener(self.hook_request_success)
events.request_failure.add_listener(self.hook_request_fail)
atexit.register(self.exit_handler)
Adn this works quiet good while I use a small amout of users in locust, around 100.
But when the users start to go up, I get the following exception:
[2021-05-31 18:40:48,430] HMG28/ERROR/root: Uncaught exception in event handler:
Traceback (most recent call last):
File "c:\python39\lib\site-packages\gevent\_socketcommon.py", line 722, in send
return self._sock.send(data, flags)
BlockingIOError: [WinError 10035] A non-blocking socket operation could not be completed immediately
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "c:\python39\lib\site-packages\locust\event.py", line 40, in fire
handler(**kwargs)
File "C:\Users\AAA\Desktop\AAA\locust_files\locustfile.py", line 60, in hook_request_success
self.sock.send(message.encode())
File "c:\python39\lib\site-packages\gevent\_socketcommon.py", line 727, in send
self._wait(self._write_event)
File "src\\gevent\\_hub_primitives.py", line 317, in gevent._gevent_c_hub_primitives.wait_on_socket
File "src\\gevent\\_hub_primitives.py", line 322, in gevent._gevent_c_hub_primitives.wait_on_socket
File "src\\gevent\\_hub_primitives.py", line 297, in gevent._gevent_c_hub_primitives._primitive_wait
gevent.exceptions.ConcurrentObjectUseError: This socket is already used by another greenlet: <bound method Waiter.switch of <gevent._gevent_c_waiter.Waiter object at 0x00000222BA8FB4F0>>
Is there a way to make the socket connections wait until they can send the data?
Searching SO for your error, I found this possibly helpful answer:
Non-Blocking error when adding timeout to python server
If you continue to have issues, you can try using a gevent compatible socket and see if that gets you the concurrency you want more easily.
I am trying out pyro4 connection between my PC and Raspberry Pi 4.
Code on my PC is:
# saved as server.py
import Pyro4, Pyro4.naming
import socket, threading
# Define an object that will be accessible over the network.
# This is where all your code should go...
#Pyro4.expose
class MessageServer(object):
def show_message(self, msg):
print("Message received: {}".format(msg))
# Start a Pyro nameserver and daemon (server process) that are accessible
# over the network. This has security risks; see
# https://pyro4.readthedocs.io/en/stable/security.html
hostname = socket.gethostname()
ns_thread = threading.Thread(
target=Pyro4.naming.startNSloop, kwargs={'host': hostname}
)
ns_thread.daemon = True # automatically exit when main program finishes
ns_thread.start()
main_daemon = Pyro4.Daemon(host=hostname)
# find the name server
ns = Pyro4.locateNS()
# register the message server as a Pyro object
main_daemon_uri = main_daemon.register(MessageServer)
# register a name for the object in the name server
ns.register("example.message", main_daemon_uri)
# start the event loop of the main_daemon to wait for calls
print("Message server ready.")
main_daemon.requestLoop()
And code on my Raspberry is:
import Pyro4
import sys
print("Message:")
msg=sys.stdin.readline().strip()
message_server = Pyro4.Proxy("PYRONAME:192.168.1.5")
message_server.show_message(msg)
Code on my PC doesn t show any errors, but when I try to send a message from raspberry i get this:
What s your message?
test
Traceback (most recent call last):
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/socketutil.py", line 102, in getIpAddress
return getaddr(config.PREFER_IP_VERSION) if ipVersion is None else getaddr(ipVersion)
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/socketutil.py", line 94, in getaddr
ip = socket.getaddrinfo(hostname or socket.gethostname(), 80, family, socket.SOCK_STREAM, socket.SOL_TCP)[0][4][0]
File "/usr/lib/python3.7/socket.py", line 748, in getaddrinfo
for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno -2] Name or service not known
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/core.py", line 515, in connect_and_handshake
sslContext=sslContext)
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/socketutil.py", line 266, in createSocket
if getIpVersion(connect[0]) == 4:
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/socketutil.py", line 68, in getIpVersion
address = getIpAddress(hostnameOrAddress)
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/socketutil.py", line 106, in getIpAddress
return getaddr(0)
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/socketutil.py", line 94, in getaddr
ip = socket.getaddrinfo(hostname or socket.gethostname(), 80, family, socket.SOCK_STREAM, socket.SOL_TCP)[0][4][0]
File "/usr/lib/python3.7/socket.py", line 748, in getaddrinfo
for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno -2] Name or service not known
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/home/pi/Desktop/client.py", line 10, in <module>
message_server.show_message(msg)
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/core.py", line 275, in __getattr__
self._pyroGetMetadata()
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/core.py", line 615, in _pyroGetMetadata
self.__pyroCreateConnection()
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/core.py", line 588, in __pyroCreateConnection
uri = _resolve(self._pyroUri, self._pyroHmacKey)
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/core.py", line 1915, in _resolve
return nameserver.lookup(uri.object)
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/core.py", line 275, in __getattr__
self._pyroGetMetadata()
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/core.py", line 615, in _pyroGetMetadata
self.__pyroCreateConnection()
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/core.py", line 596, in __pyroCreateConnection
connect_and_handshake(conn)
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/core.py", line 549, in connect_and_handshake
raise ce
Pyro4.errors.CommunicationError: cannot connect to ('JAKOB-PC', 9090): [Errno -2] Name or service not known
My PC has its firewall disabled, so there shouldn t be any problem with that. My local ip is 192.168.1.5.
I am using a headless Raspberry and write code on it with puTTY and VNC.
I have googled this error but couldn t find any answers. Any help would be appreciated.
I did this
#
# Server.py
#
from __future__ import print_function
import Pyro4
#Pyro4.expose
#Pyro4.behavior(instance_mode="single")
class Messenger(object):
# This is a constructor
def __init__(self):
pass
# This method will be called on the server
def send_message(self, name, message):
print("[{0}] {1}".format(name, message))
def main():
Pyro4.Daemon.serveSimple(
{
Messenger: "example.messenger"
},
ns=True)
if __name__ == "__main__":
main()
#
# Client.py
#
# This is the code that visits the warehouse.
import sys
import Pyro4
import Pyro4.util
sys.excepthook = Pyro4.util.excepthook
messenger = Pyro4.Proxy("PYRONAME:example.messenger#192.168.1.5")
messenger.send_message("Tim", "Hello!")
Then ran
python -m Pyro4.naming -n 192.168.1.5
python Server.py
python Client.py
In short I couldn't solve the problem with Pyro and (almost) no one helped so I decided to use 'websockets' instead.
You can read the documentation here but I'll explain it here anyway.
First of all you need two devices with network connection. You also have to run python 3.6.1 on both of them. After that you also need to install websockets if you don't have them already with pip install websockets or as I had to do it with pip3 install websockets.
Code below runs on the server and handles messages you send to it from client. Function 'hello' is a simple example of processing request and sending back a response. 'request' is the data server receives, that data must be bytes, string on iterable. Response is made by converting request to integer, squaring it and converting it back to string. This response is then sent back to client.
'start_server' defines the server, function that will define its behavior(hello), ip address on witch the server is running on(192.168.1.117) and port on witch it will receive requests(8765).
!/usr/bin/env python
import asyncio
import websockets
print("Running...")
async def hello(websocket, path):
request = await websocket.recv()
print("Request: " + request)
response = str(int(request)*int(request))
await websocket.send(response)
print("Response:" + response)
start_server = websockets.serve(hello, "192.168.1.117", 8765)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
Next bit is code on the client. 'uri' is ip and port of the server. Function 'tellServ' asks you to input some data('tell' variable) and sends it to the server. After that it waits for reply and once it gets it it prints it out. In this case if I would input number "6" server would reply with "36". Function loop is in a while loop so I can send multiple numbers without having to restart the script.
#!/usr/bin/env python
import asyncio
import websockets
uri = "ws://192.168.1.117:8765"
async def tellServ():
async with websockets.connect(uri) as websocket:
tell = input("Podatek ki ga posles: ")
await websocket.send(tell)
reply = await websocket.recv()
print("Odgovor:")
print(reply)
while 1:
asyncio.get_event_loop().run_until_complete(tellServ())
I am trying to establish a long running Pull subscription to a Google Cloud PubSub topic.
I am using a code very similar to the example given in the documentation here, i.e.:
def receive_messages(project, subscription_name):
"""Receives messages from a pull subscription."""
subscriber = pubsub_v1.SubscriberClient()
subscription_path = subscriber.subscription_path(
project, subscription_name)
def callback(message):
print('Received message: {}'.format(message))
message.ack()
subscriber.subscribe(subscription_path, callback=callback)
# The subscriber is non-blocking, so we must keep the main thread from
# exiting to allow it to process messages in the background.
print('Listening for messages on {}'.format(subscription_path))
while True:
time.sleep(60)
The problem is that I'm receiving the following traceback sometimes:
Exception in thread Consumer helper: consume bidirectional stream:
Traceback (most recent call last):
File "/usr/lib/python3.5/threading.py", line 914, in _bootstrap_inner
self.run()
File "/usr/lib/python3.5/threading.py", line 862, in run
self._target(*self._args, **self._kwargs)
File "/path/to/google/cloud/pubsub_v1/subscriber/_consumer.py", line 248, in _blocking_consume
self._policy.on_exception(exc)
File "/path/to/google/cloud/pubsub_v1/subscriber/policy/thread.py", line 135, in on_exception
raise exception
File "/path/to/google/cloud/pubsub_v1/subscriber/_consumer.py", line 234, in _blocking_consume
for response in response_generator:
File "/path/to/grpc/_channel.py", line 348, in __next__
return self._next()
File "/path/to/grpc/_channel.py", line 342, in _next
raise self
grpc._channel._Rendezvous: <_Rendezvous of RPC that terminated with (StatusCode.UNAVAILABLE, The service was unable to fulfill your request. Please try again. [code=8a75])>
I saw that this was referenced in another question but here I am asking to how to handle it properly in Python. I have tried to wrap the request in an exception but it seems to run in the background and I am not able to retry in case of that error.
A somewhat hacky approach that is working for me is a custom policy_class. The default one has an on_exception function that ignores DEADLINE_EXCEEDED. You can make a class that inherits the default and also ignores UNAVAILABLE. Mine looks like this:
from google.cloud import pubsub
from google.cloud.pubsub_v1.subscriber.policy import thread
import grpc
class AvailablePolicy(thread.Policy):
def on_exception(self, exception):
"""The parent ignores DEADLINE_EXCEEDED. Let's also ignore UNAVAILABLE.
I'm not sure what triggers that error, but if you ignore it, your
subscriber seems to work just fine. It's probably an intermittent
thing and it reconnects later if you just give it a chance.
"""
# If this is UNAVAILABLE, then we want to retry.
# That entails just returning None.
unavailable = grpc.StatusCode.UNAVAILABLE
if getattr(exception, 'code', lambda: None)() == unavailable:
return
# For anything else, fallback on super.
super(AvailablePolicy, self).on_exception(exception)
subscriber = pubsub.SubscriberClient(policy_class=AvailablePolicy)
# Continue to set up as normal.
It looks a lot like the original on_exception just ignores a different error. If you want, you can add some logging whenever the exception is thrown and verify that everything still works. Future messages will still come through.
I have the following situation; My Pyro4 project has a server and a client. The server contains a method which need to call 2 callbacks on the same callback object. So class Callback has two callback methods: Callback() and SecondCallback(). There is some delay between the calls of those callback methods. I've simulated this delay in my example by calling time.sleep.
I need to set a timeout on Pyro4 (Pyro4.config.COMMTIMEOUT), because without one, the Pyro4 daemon will never break out of the requestLoop method. This works perfectly when calling just one callback method, but when you have to call a second callback method, the Pyro4 callback daemon closes the connection after the first callback method was called + the timeout.
I've tried to set the timeout to a bigger amount, but this timeout is also the time the requestLoop method blocks untill it processes the loopCondition.
An example script which demonstrates my issue is included below. You need to start it by starting a server after you started the Pyro4 nameserver:
python -m Pyro4.naming
python test.py -s
And afterwards starting a client in a new cmd window:
python test.py
Test.py
import Pyro4, time
from argparse import ArgumentParser
ip = "127.0.0.1"
class Server:
def __init__(self):
pass
def ActionOne(self):
return "Foo"
def ActionTwo(self):
return "Bar"
#Pyro4.oneway
def ActionThree(self, callback):
time.sleep(4)
callback.Callback()
time.sleep(3)
callback.SecondCallback()
class Callback:
def __init__(self):
self.Executed = False
pass
def Callback(self):
print "FooBar"
def SecondCallback(self):
print "raBooF"
self.Executed = True
def loopWhile(condition):
while condition:
time.sleep(.1)
if __name__ == "__main__":
parser = ArgumentParser()
parser.add_argument("--server", "-s", action="store_true")
args = parser.parse_args()
if(args.server):
print "Server"
daemon = Pyro4.core.Daemon(host=ip)
uri = daemon.register(Server())
ns = Pyro4.naming.locateNS(host=ip)
ns.register("server", uri)
daemon.requestLoop()
pass
else:
print "Client"
Pyro4.config.COMMTIMEOUT = .5
ns = Pyro4.naming.locateNS(host=ip)
serverUri = ns.lookup("server")
proxy = Pyro4.core.Proxy(serverUri)
print proxy.ActionOne()
print proxy.ActionTwo()
daemon = Pyro4.core.Daemon(host=ip)
callback = Callback()
daemon.register(callback)
proxy.ActionThree(callback)
daemon.requestLoop(lambda: not callback.Executed)
print "FINISHED"
The result of this script:
Server:
Server
Exception in thread Thread-17:
Traceback (most recent call last):
File "C:\Program Files (x86)\IronPython 2.7\Lib\threading.py", line 552, in _T
hread__bootstrap_inner
self.run()
File "C:\Program Files (x86)\IronPython 2.7\Lib\threading.py", line 505, in ru
n
self.__target(*self.__args, **self.__kwargs)
File "test.py", line 22, in ActionThree
callback.SecondCallback()
File "C:\Program Files (x86)\IronPython 2.7\lib\site-packages\Pyro4\core.py",
line 171, in __call__
return self.__send(self.__name, args, kwargs)
File "C:\Program Files (x86)\IronPython 2.7\lib\site-packages\Pyro4\core.py",
line 410, in _pyroInvoke
msg = message.Message.recv(self._pyroConnection, [message.MSG_RESULT], hmac_
key=self._pyroHmacKey)
File "C:\Program Files (x86)\IronPython 2.7\lib\site-packages\Pyro4\message.py
", line 168, in recv
msg = cls.from_header(connection.recv(cls.header_size))
File "C:\Program Files (x86)\IronPython 2.7\lib\site-packages\Pyro4\socketutil
.py", line 448, in recv
return receiveData(self.sock, size)
File "C:\Program Files (x86)\IronPython 2.7\lib\site-packages\Pyro4\socketutil
.py", line 190, in receiveData
raise ConnectionClosedError("receiving: connection lost: " + str(x))
ConnectionClosedError: receiving: connection lost: [Errno 10022] A request to se
nd or receive data was disallowed because the socket is not connected and (when
sending on a datagram socket using a sendto call) no address was supplied
Client:
Client
Foo
Bar
FooBar
My final question is: How do I prevent Pyro4 from closing the connection after COMMTIMEOUT expired when a second callback is called?
I hope all this information is clear enough to understand.
Thank you for your help.
For future reference:
I was able to restart the connection to the callback by calling:
callback._pyroReconnect()
Just before calling the second callback method
Your question is a bit strange, to be honest.
On the one hand you're configuring COMMTIMEOUT to a (very low) value of 0.5 seconds, thereby enabling the concept of timeouts. On the other hand you're asking to not get a timeout that closes the connection on the server. What is it you want?
But yeah, you can use _pyroReconnect to reconnect a proxy that has been disconnected. Also see the readmes and code of the autoreconnect and disconnects examples that come with Pyro4.
I am using Flask-Socketio on my server that is running Flask and my clients run javascript. All my clients connect to the server using the namespace '/test'. Upon a certain action on the client, I want the client to trigger a function on the server that iterates through all the connected clients. I am using the following code segment to iterate through the list of connected clients:
for sessid, socket in request.namespace.socket.server.sockets.items():
print "socket id : %r" % (socket['/test'].session['id'])
where each connection has an 'id' key assigned to it on connection.
However sometimes the server gives the following error indicating that the namespace key was not found:
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/gevent/greenlet.py", line 327, in run
result = self._run(*self.args, **self.kwargs)
File "/usr/local/lib/python2.7/dist-packages/socketio/virtsocket.py", line 403, in_receiver_loop
retval = pkt_ns.process_packet(pkt)
File "/usr/local/lib/python2.7/dist-packages/socketio/namespace.py", line 155, in process_packet
return self.process_event(packet)
File "/usr/local/lib/python2.7/dist-packages/flask_socketio/__init__.py", line 64, in process_event
return self.socketio._dispatch_message(app, self, message, args)
File "/usr/local/lib/python2.7/dist-packages/flask_socketio/__init__.py", line 137, in _dispatch_message
ret = self.messages[namespace.ns_name][message](*args)
File "/home/ubuntu/flask-app/current/py/flaskapp/main/sockets.py", line 190, in gameInitialisedByClient
print "id : %r random: %r" % (socket['/test'].session['id'], socket['/test'].session['random'])
File "/usr/local/lib/python2.7/dist-packages/socketio/virtsocket.py", line 190, in __getitem__
return self.active_ns[key]
KeyError: '/test'
<Greenlet at 0x7f483bc6bf50: <bound method Socket._receiver_loop of <socketio.virtsocket.Socket object at 0x7f483a5ac6d0>>> failed with KeyError
I do not understand why i get this error since all my sockets that connect to the server are connecting on the same namespace. Moreover, this error is experienced only during a fraction of the function calls. Why isn't this error consistent?
Is there a better way in which I could iterate through the list of connected clients?
You are iterating over a private data structure of package gevent-socketio, so unexpected things can happen.
I do not know the internals of this package to tell you why this happens, but I think a much safer approach would be for you to build your own list of connected clients. You can add and remove clients to your list in the connect and disconnect handlers. I think something like this will work:
clients = []
#socketio.on('connect', namespace='/test')
def connect():
clients.append(request.namespace)
#socketio.on('disconnect', namespace='/test')
def disconnect():
clients.remove(request.namespace)