Skip to content

Commit b7f2cb5

Browse files
author
Roberto De Ioris
authored
Update AsyncIOAndUnrealEngine.md
1 parent ed5f653 commit b7f2cb5

1 file changed

Lines changed: 55 additions & 0 deletions

File tree

‎tutorials/AsyncIOAndUnrealEngine.md‎

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,26 +149,37 @@ for task in asyncio.Task.all_tasks():
149149

150150
## A simple tcp server spawning Character's in the editor
151151

152+
This is a more complex (but more useful) example, showing how to open a tcp server in your UE instance, to allow external communication.
153+
154+
Here, the protocol is pretty dumb: each lien sent by a client will spawn a new Character with the name set to the string passed by the client.
155+
152156
```python
153157
import asyncio
154158
import ue_asyncio
155159
from unreal_engine.classes import Character
156160

161+
# cleanup previous tasks
157162
for task in asyncio.Task.all_tasks():
158163
task.cancel()
159164

165+
# this is called whenever a new client connects
160166
async def new_client_connected(reader, writer):
161167
name = writer.get_extra_info('peername')
162168
ue.log('new client connection from {0}'.format(name))
163169
while True:
170+
# wait for a line
164171
data = await reader.readline()
165172
if not data:
166173
break
167174
ue.log('client {0} issued: {1}'.format(name, data.decode()))
175+
# spawn a new Character and set its label
168176
new_actor = ue.get_editor_world().actor_spawn(Character)
169177
new_actor.set_actor_label(data.decode())
170178
ue.log('client {0} disconnected'.format(name))
171179

180+
# this spawns the server
181+
# the try/finally trick allows for gentle shutdown of the server
182+
# see below for more infos about exception management
172183
async def spawn_server(host, port):
173184
try:
174185
coro = await asyncio.start_server(new_client_connected, host, port)
@@ -183,12 +194,15 @@ asyncio.ensure_future(spawn_server('192.168.173.45', 8885))
183194

184195
## Redis pubsub
185196

197+
Another useful example, here we subscribe to a remote redis queue, and we wait for messages
198+
186199
```python
187200
import asyncio
188201
import ue_asyncio
189202
import unreal_engine as ue
190203
import aioredis
191204

205+
# cleanup previous tasks
192206
for task in asyncio.Task.all_tasks():
193207
task.cancel()
194208

@@ -207,8 +221,49 @@ asyncio.ensure_future(wait_for_redis())
207221

208222
## Managinx exceptions in non-awaited coroutines
209223

224+
By default exceptions thrown in a non-awaited coroutine (like the ones you spawn with asyncio.ensure_future) are not propagated.
225+
226+
There are various tricks you can use to manage them. The simplest one is trapping exceptions in the coroutine itself and reporting them as UE errors:
227+
228+
```python
229+
async def connecto_to_a_broken_redis():
230+
try:
231+
redis = await aioredis.create_redis(('192.168.173.27', 6379))
232+
...
233+
except Exception as e:
234+
ue.log_error(e)
235+
finally:
236+
# here you can run important cleanup tasks
237+
redis.close()
238+
```
239+
240+
A more elegant approach is adding a callback whenever a coroutine ends, in which we will check if it died for an exception or it has been cancelled (or obviously it has simply finished its work):
241+
242+
```python
243+
244+
async def broken_coroutine():
245+
raise Exception('OOOOOOPS')
246+
247+
def check_exception(coro):
248+
# if the coroutine has been cancelled, just ignore it
249+
if coro.cancelled():
250+
return
251+
# check if the coroutine ended with an exception
252+
exc = coro.exception()
253+
# in such a case raise/propagate it
254+
if exc:
255+
raise exc
256+
257+
coroutine = asyncio.ensure_future(broken_coroutine())
258+
coroutine.add_done_callback(check_exception)
259+
```
260+
261+
Remember, you only need to pay attention to non-awaited coroutines, the others will correctly propagate the exception to the task awaiting it (obviously this task could be a not-awaited one, so as a general rule, add a callback every time you use asyncio.ensure_future())
262+
210263
## aiohttp
211264

265+
This is probably the most known third-party asyncio module. It basically interact with every HTTP aspect (server, client, websockets....)
266+
212267
## asyncio in your actors
213268

214269
### A simple Icecast/Shoutcast streaming radio Component

0 commit comments

Comments
 (0)