Chris Angelico <ros...@gmail.com>: > Hmm. I'm not sure about that last bit. In order to properly support > asynchronous I/O and the concurrency and reentrancy that that implies, > you basically need all the same disciplines that you would for > threaded programming
Correct. Python's asyncio closely mirrors threads in its API and thought model. An async is like a thread except that you know the control will only be relinquished at an "await" statement. Thus, you probably need far less locking. One visible difference between asyncs and threads is the fact that threads don't need a special "await" construct. Instead, ordinary function calls support context switching deep down in the Python VM and the operating system. Each "await" explicitly marks a state in a state machine. Whenever you turn a nonblocking function into a blocking one, you will need to change the function call to an await statement. Asyncs have a couple of distinct advantages over threads: * You can await multiple events in a single statement allowing for multiplexing. Threads can only wait for a single event. * Asyncs can be canceled; in general, threads can't. > But maybe I'm too comfortable with threads. It's entirely possible; my > first taste of reentrancy was interrupt handling in real mode 80x86 > assembly language, and in comparison to that, threads are pretty > benign! I steer clear of threads if I can because: * No multiplexing. * No cancellation. * Deadlocks and/or race conditions are virtually guaranteed. * Error symptoms are highly nonlocal making debugging very tricky. Instead, I strongly prefer asynchronous programming and multiprocessing. However, I'm afraid Python is following an unfortunate trend with asyncio. Deep down concurrent programming involves finite state machines. State machines can be expressed in many ways; traditionally, you have SDL diagrams, state/event matrices etc. Asyncio marks states with inline "await" keywords. Toy examples look really enticing and readable compared with the more traditional implementation methods. However, real-world code can quickly become spaghetti as the dozens of cells of the state/event matrix are implemented. My favorite asynchronous development model is the "callback hell," where each cell of the state/event matrix is represented by a method (or at least a switch case in C) and each state has an explicit name in the source code. The resulting code is still hard to read and hard to get right, but that complexity is unavoidable because reality just is that complex. Marko -- https://mail.python.org/mailman/listinfo/python-list