Jan-29-2020, 10:17 AM
asyncio.StreamReader
has some convenience functions like readuntil
, readline
, readexcatly
This code could handle many simultaneous connections.
I use type hints in the first function, to show
what is the expected data and what is returned by this function.
The function
handle_connection
has also type hints.I used this inside an IDE (PyCharm), which gives you auto complete for this type.
I hope this is not too much. You don't have to understand everything.
asyncio is a little bit complex and has some quirks.
import asyncio from typing import List def convert_values(data: bytes) -> List[float]: """ Function to convert floats delimited by a comma into a list with floats. The eof marker * at the end will be removed. """ try: # 0. The data type is bytes # 1. rstrip the * # 2. split by , -> list with bytes # 3. MAP: call float for each element in the list # 4. consume the map by a list, map is lazy evaluated values = list(map(float, data.rstrip(b'*').split(b','))) # or written in more lines and using a list comprehension # data = data.rstrip(b'*').split(b',') # data is now a list with bytes # the function float can handle both: bytes and str # whitespaces are removed automatically by this function # values = [float(val) for val in data] except ValueError: # In case of an error, return a empty list return [] # no error -> return values return values async def handle_connection(reader: asyncio.StreamReader, writer: asyncio.StreamWriter): addr, port = writer.get_extra_info('peername') print(f'Client {addr} connected.') while True: try: # read until * # a timeout should be used future = reader.readuntil(b'*') # bytes, not str data = await asyncio.wait_for(future, timeout=10) except asyncio.TimeoutError: print(f'Got timeout from {addr}') writer.close() await writer.wait_closed() # use break or return to stop the # handle_connection # forgetting to leave this loop, will raise the # exception: asyncio.IncompleteReadError break else: # no error, print the values values = convert_values(data) print(values) # or do something else with it. async def main(): """ Copy and Paste from: https://docs.python.org/3/library/asyncio-stream.html#tcp-echo-server-using-streams """ server = await asyncio.start_server(handle_connection, 'localhost', 1234) async with server: await server.serve_forever() # convenience function # https://docs.python.org/3/library/asyncio-task.html#asyncio.run asyncio.run(main())You don't have to use
asyncio
, but the function convert_values
explains how your original problem could be solved. The length of example data seems to be variable. If the data is sent over and over again and * is the start/end marker, then you need to change the timeout. Maybe it's too short or too long. Depends how fast the data is sent over the wire.
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
All humans together. We don't need politicians!