Herramientas de usuario

Herramientas del sitio


wiki2:python3

Diferencias

Muestra las diferencias entre dos versiones de la página.

Enlace a la vista de comparación

Ambos lados, revisión anterior Revisión previa
Próxima revisión
Revisión previa
wiki2:python3 [2020/06/20 12:54]
alfred [The event loop]
wiki2:python3 [2022/10/12 19:03] (actual)
Línea 88: Línea 88:
 Co-routines are functions that in a way similar to green threads are executed in a single thread and process. However, they are not so costly as are not managed by the operating system but by the **event loop**. Co-routines are functions that in a way similar to green threads are executed in a single thread and process. However, they are not so costly as are not managed by the operating system but by the **event loop**.
  
 +For an advance use go to [[wiki2:​python:​notes#​advanced_asyncio|Advanced asyncio]].
 ==== Basic points ==== ==== Basic points ====
  
Línea 275: Línea 276:
     print(await fut)  # Wait until *fut* has a result (1 second) and print it.     print(await fut)  # Wait until *fut* has a result (1 second) and print it.
  
 +asyncio.run(main())
 +</​code>​
 +
 +An instance of ''​Executor''​ provides methods to execute calls asynchronously. It should not be used directly, but through its concrete subclasses.
 +
 +<code python>
 +async def main():
 +    loop = asyncio.get_running_loop()
 +    result = await loop.run_in_executor( ​     # 1. Returns a Future.Executor
 +        None, blocking_io)
 +    print('​default thread pool', result)
 +    with concurrent.futures.ThreadPoolExecutor() as pool:      # 2. Run in a custom thread pool: 
 +        result = await loop.run_in_executor(
 +            pool, blocking_io)
 +        print('​custom thread pool', result)
 +    with concurrent.futures.ProcessPoolExecutor() as pool:    # 3. Run in a custom process pool:
 +        result = await loop.run_in_executor(
 +            pool, cpu_bound)
 +        print('​custom process pool', result)
 +</​code>​
 +
 +''​ThreadPoolExecutor''​ uses a pool of threads in the same way than ''​ProcessPoolExecutor''​ uses a pool of processes.
 +<code python>
 +executor = ThreadPoolExecutor(max_workers=2)
 +a = executor.submit(wait_on_b)
 +b = executor.submit(wait_on_a)
 +</​code>​
 +
 +==== Other tools ====
 +
 +=== Streams ===
 +  * [[https://​docs.python.org/​3/​library/​asyncio-stream.html]]
 +These allow to manage IO resources (sockets) asynchronously.
 +
 +=== Synchronization ===
 +  * [[https://​docs.python.org/​3/​library/​asyncio-sync.html]]
 +
 +You can make use of the usual tools for synchronize co-routines (Lock, Event, Condition, Semaphore, BoundedSemaphore).
 +
 +=== Queues ===
 +  * [[https://​docs.python.org/​3/​library/​asyncio-queue.html]]
 +
 +Asynchronous queues that can be used to distribute workload between several concurrent tasks:
 +<code python>
 +import asyncio
 +import random
 +import time
 +
 +async def worker(name,​ queue):
 +    while True:
 +        sleep_for = await queue.get()
 +        await asyncio.sleep(sleep_for)
 +        queue.task_done()
 +
 +async def main():
 +    queue = asyncio.Queue()
 +    total_sleep_time = 0
 +    for _ in range(20):
 +        sleep_for = random.uniform(0.05,​ 1.0)
 +        total_sleep_time += sleep_for
 +        queue.put_nowait(sleep_for)
 +
 +    # Create three worker tasks to process the queue concurrently.
 +    tasks = []
 +    for i in range(3):
 +        task = asyncio.create_task(worker(f'​worker-{i}',​ queue))
 +        tasks.append(task)
 +    # Wait until the queue is fully processed.
 +    started_at = time.monotonic()
 +    await queue.join()
 +    total_slept_for = time.monotonic() - started_at
 +    # Cancel our worker tasks.
 +    for task in tasks:
 +        task.cancel()
 +    # Wait until all worker tasks are cancelled.
 +    await asyncio.gather(*tasks,​ return_exceptions=True)
 +
 +    print('​===='​)
 +    print(f'​3 workers slept in parallel for {total_slept_for:​.2f} seconds'​)
 +    print(f'​total expected sleep time: {total_sleep_time:​.2f} seconds'​)
 asyncio.run(main()) asyncio.run(main())
 </​code>​ </​code>​
Línea 312: Línea 393:
  
   * [[https://​news.ycombinator.com/​item?​id=23498742|Discussion on Hacker News]]   * [[https://​news.ycombinator.com/​item?​id=23498742|Discussion on Hacker News]]
 +
 +=== functools.partial for passing arguments ===
 +''​functools.partial''​ allows to create a function that not requires arguments from one that requires them.
 +<code python>
 +loop.call_soon(partial(print,​ "​Hello",​ flush=True))
 +</​code>​
 +
 +=== Stop co-routines when signals ===
 +<code python>
 +import asyncio
 +import functools
 +import os
 +import signal
 +
 +def ask_exit(signame,​ loop):
 +    print("​got signal %s: exit" % signame)
 +    loop.stop()
 +
 +async def main():
 +    loop = asyncio.get_running_loop()
 +
 +    for signame in {'​SIGINT',​ '​SIGTERM'​}:​
 +        loop.add_signal_handler(
 +            getattr(signal,​ signame),
 +            functools.partial(ask_exit,​ signame, loop))
 +
 +    await asyncio.sleep(3600)
 +
 +print("​Event loop running for 1 hour, press Ctrl+C to interrupt."​)
 +print(f"​pid {os.getpid()}:​ send SIGINT or SIGTERM to exit."​)
 +
 +asyncio.run(main())
 +</​code>​
 +
 +===== Enums =====
 +
 +<code python>
 +from enum import Enum
 +
 +class Numbers(Enum):​
 +    ONE = 1
 +    TWO = 2
 +
 +number = Numbers(2) ​ # <​Numbers.TWO:​ 2>
 +number1 = Numbers["​ONE"​] ​ # <​Numbers.TWO:​ 2>
 +members = [n for n in Numbers] ​ # [<​Numbers.ONE:​ 1>, <​Numbers.TWO:​ 2>]
 +values = [n.value for n in Numbers] ​ # [1, 2]
 +</​code>​
 +
 +==== Links ====
 +
 +  * https://​realpython.com/​python-enum/​
 +
 +===== Python type checking =====
 +
 +<​code>​
 +pi: float = 3.142
 +
 +def headline(text:​ str, align: bool = True) -> str:
 +    pass
 +    ​
 +    ​
 +</​code>​
 +
 +The ''​MyPy''​ library allows to check code files.
 +
 +<​code>​
 +>>>​ names: list = ["​Guido",​ "​Jukka",​ "​Ivan"​]
 +>>>​ version: tuple = (3, 7, 1)
 +>>>​ options: dict = {"​centered":​ False, "​capitalize":​ True}
 +>>>​ from typing import Dict, List, Tuple
 +>>>​ names: List[str] = ["​Guido",​ "​Jukka",​ "​Ivan"​]
 +>>>​ version: Tuple[int, int, int] = (3, 7, 1)
 +>>>​ options: Dict[str, bool] = {"​centered":​ False, "​capitalize":​ True}
 +</​code>​
 +
 +<​code>​
 +import random
 +from typing import Any, Sequence
 +
 +def choose(items:​ Sequence[Any]) -> Any:
 +    return random.choice(items)
 +</​code>​
 +
 +<​code>​
 +class Animal:
 +    def __init__(self,​ name: str, birthday: date) -> None:
 +        self.name = name
 +        self.birthday = birthday
 +
 +    @classmethod
 +    def newborn(cls,​ name: str) -> "​Animal":​
 +        return cls(name, date.today())
 +
 +    def twin(self, name: str) -> "​Animal":​
 +        cls = self.__class__
 +        return cls(name, self.birthday)
 +</​code>​
 +
 +<​code>​
 +def headline(text,​ width=80, fill_char="​-"​):​
 +    # type: (str, int, str) -> str
 +    return f" {text.title()} "​.center(width,​ fill_char)
 +
 +def headline(
 +    text,           # type: str
 +    width=80, ​      # type: int
 +    fill_char="​-", ​ # type: str
 +):                  # type: (...) -> str
 +    return f" {text.title()} "​.center(width,​ fill_char)
 +</​code>​
 ===== Notes ===== ===== Notes =====
  
wiki2/python3.1592657669.txt.gz · Última modificación: 2020/06/20 13:54 (editor externo)