From 8a553cef4d2eefa58f634002b3fb4c084661ad0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jure=20=C5=A0orn?= Date: Sat, 27 Jan 2024 09:22:02 +0100 Subject: [PATCH 001/345] Threading --- README.md | 2 +- index.html | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6b516af34..7ff363689 100644 --- a/README.md +++ b/README.md @@ -2150,7 +2150,7 @@ with : # Enters the block by calling acq = .cancel() # Cancels or returns False if running/finished. = as_completed() # Next() waits for next completed Future. ``` -* **Map() and as\_completed() also accept 'timeout' argument. It causes TimeoutError when next() is called if result isn't available in 'timeout' seconds from the original call.** +* **Map() and as\_completed() also accept 'timeout'. It causes futures.TimeoutError when next() is called. Map() times from original call and as_completed() from first call to next().** * **Exceptions that happen inside threads are raised when next() is called on map's iterator or when result() is called on a Future. Its exception() method returns exception or None.** * **ProcessPoolExecutor provides true parallelism, but everything sent to/from workers must be [pickable](#pickle). Queues must be sent using executor's 'initargs' and 'initializer' parameters.** diff --git a/index.html b/index.html index 285d183be..918cac50f 100644 --- a/index.html +++ b/index.html @@ -54,7 +54,7 @@
- +
@@ -1774,7 +1774,7 @@

Format

# Next() waits for next completed Future.
    -
  • Map() and as_completed() also accept 'timeout' argument. It causes TimeoutError when next() is called if result isn't available in 'timeout' seconds from the original call.
  • +
  • Map() and as_completed() also accept 'timeout'. It causes futures.TimeoutError when next() is called. Map() times from original call and as_completed() from first call to next().
  • Exceptions that happen inside threads are raised when next() is called on map's iterator or when result() is called on a Future. Its exception() method returns exception or None.
  • ProcessPoolExecutor provides true parallelism, but everything sent to/from workers must be pickable. Queues must be sent using executor's 'initargs' and 'initializer' parameters.
@@ -2932,7 +2932,7 @@

Format

-
>>> [l+r for l in 'abc' for r in 'abc']
+
>>> [l+r for l in 'abc' for r in 'abc']             # Inner loop is on the right side.
 ['aa', 'ab', 'ac', ..., 'cc']
 

Map, Filter, Reduce

from functools import reduce
@@ -662,11 +662,11 @@
 <iter> = filter(lambda x: x > 5, range(10))         # Or: iter([6, 7, 8, 9])
 <obj>  = reduce(lambda out, x: out + x, range(10))  # Or: 45
 
-

Any, All

<bool> = any(<collection>)                          # Is `bool(<el>)` True for any element.
-<bool> = all(<collection>)                          # Is True for all elements or empty.
+

Any, All

<bool> = any(<collection>)                          # Is `bool(<el>)` True for any el?
+<bool> = all(<collection>)                          # Is True for all or is it empty?
 
-

Conditional Expression

<obj> = <exp> if <condition> else <exp>             # Only one expression gets evaluated.
+

Conditional Expression

<obj> = <exp> if <condition> else <exp>             # Only one expression is evaluated.
 
>>> [a if a else 'zero' for a in (0, 1, 2, 3)]      # `any([0, '', [], None]) == False`
@@ -1844,7 +1844,7 @@ 

Format

# Logs to the root logger. <Logger> = logging.getLogger(__name__) # Logger named after the module. <Logger>.<level>(<str>) # Logs to the logger. -<Logger>.exception(<str>) # Calls error() with caught exception. +<Logger>.exception(<str>) # Error() that appends caught exception.

Setup

logging.basicConfig(
     filename=None,                                   # Logs to console (stderr) by default.
@@ -2311,7 +2311,7 @@ 

Format

# To rotate use Image's rotate() and paste(). <ImageDraw>.polygon((x1, y1, x2, y2, ...)) # Last point gets connected to the first. <ImageDraw>.ellipse((x1, y1, x2, y2)) # To rotate use Image's rotate() and paste(). -<ImageDraw>.text((x, y), text, font=<Font>) # `<Font> = ImageFont.truetype(<path>, size)` +<ImageDraw>.text((x, y), <str>, font=<Font>) # `<Font> = ImageFont.truetype(<path>, size)`

    @@ -2932,7 +2932,7 @@

    Format

Runs a terminal game where you control an asterisk that must avoid numbers:

import asyncio, collections, curses, curses.textpad, enum, random, time
+
import asyncio as aio
+
+ + +
<coro> = <async_func>(<args>)             # Creates a coroutine.
+<obj>  = await <coroutine>                # Starts the coroutine and returns result.
+<task> = aio.create_task(<coroutine>)     # Schedules coroutine for execution.
+<obj>  = await <task>                     # Returns result.
+
+
<coro> = aio.gather(<coro/task>, ...)     # Schedules coroutines. Returns results when awaited.
+<coro> = aio.wait(<tasks>, …)             # `aio.ALL/FIRST_COMPLETED`. Returns (done, pending).
+<iter> = aio.as_completed(<coros/tasks>)  # Iter of coros. All return next result when awaited.
+
+

Runs a terminal game where you control an asterisk that must avoid numbers:

import asyncio, collections, curses, curses.textpad, enum, random, time
 
-P = collections.namedtuple('P', 'x y')         # Position
-D = enum.Enum('D', 'n e s w')                  # Direction
-W, H = 15, 7                                   # Width, Height
+P = collections.namedtuple('P', 'x y')    # Position
+D = enum.Enum('D', 'n e s w')             # Direction
+W, H = 15, 7                              # Width, Height
 
 def main(screen):
-    curses.curs_set(0)                         # Makes cursor invisible.
-    screen.nodelay(True)                       # Makes getch() non-blocking.
-    asyncio.run(main_coroutine(screen))        # Starts running asyncio code.
+    curses.curs_set(0)                    # Makes cursor invisible.
+    screen.nodelay(True)                  # Makes getch() non-blocking.
+    asyncio.run(main_coroutine(screen))   # Starts running asyncio code.
 
 async def main_coroutine(screen):
     moves = asyncio.Queue()
@@ -1932,40 +1943,30 @@ 

Format

async def human_controller(screen, moves): while True: key_mappings = {258: D.s, 259: D.n, 260: D.w, 261: D.e} - ch = screen.getch() - if d := key_mappings.get(ch): + if d := key_mappings.get(screen.getch()): moves.put_nowait(('*', d)) await asyncio.sleep(0.005) async def model(moves, state): while state['*'] not in (state[id_] for id_ in range(10)): id_, d = await moves.get() - x, y = state[id_] deltas = {D.n: P(0, -1), D.e: P(1, 0), D.s: P(0, 1), D.w: P(-1, 0)} - dx, dy = deltas[d] - state[id_] = P((x + dx) % W, (y + dy) % H) + state[id_] = P((state[id_].x + deltas[d].x) % W, (state[id_].y + deltas[d].y) % H) async def view(state, screen): offset = P(curses.COLS//2 - W//2, curses.LINES//2 - H//2) while True: screen.erase() - curses.textpad.rectangle(screen, offset.y-1, offset.x-1, offset.y+H, offset.x+W) + curses.textpad.rectangle(screen, offset.y-1, offset.x-1, offset.y+H, offset.x+W) for id_, p in state.items(): - screen.addstr( - offset.y + (p.y - state['*'].y + H//2) % H, - offset.x + (p.x - state['*'].x + W//2) % W, - str(id_) - ) + screen.addstr(offset.y + (p.y - state['*'].y + H//2) % H, + offset.x + (p.x - state['*'].x + W//2) % W, str(id_)) screen.refresh() await asyncio.sleep(0.005) if __name__ == '__main__': - start_time = time.perf_counter() curses.wrapper(main) - print(f'You survived {time.perf_counter() - start_time:.2f} seconds.') -

- - +


Libraries

#Progress Bar

# $ pip3 install tqdm
@@ -2932,7 +2933,7 @@ 

Format