Convert Figma logo to code with AI

dabeaz logocurio

Good Curio!

4,024
241
4,024
20

Top Related Projects

15,061

Asynchronous HTTP client/server framework for asyncio and Python

6,145

Trio – a friendly Python library for async concurrency and I/O

10,269

Ultra fast asyncio event loop.

10,027

The little ASGI framework that shines. 🌟

75,446

FastAPI framework, high performance, easy to learn, fast to code, ready for production

21,707

Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed.

Quick Overview

Curio is a Python library for concurrent programming using coroutines and the async/await syntax. It provides a small, carefully designed API for performing concurrent I/O and task management, with a focus on simplicity and ease of use.

Pros

  • Simple and intuitive API for concurrent programming
  • Lightweight and efficient, with minimal overhead
  • Excellent documentation and examples
  • Strong support for unit testing of asynchronous code

Cons

  • Smaller ecosystem compared to asyncio
  • Limited third-party library support
  • May require more manual management of tasks compared to other frameworks
  • Not as widely adopted as asyncio in the Python community

Code Examples

  1. Basic task creation and execution:
import curio

async def hello():
    print('Hello, World!')

async def main():
    await curio.spawn(hello())

if __name__ == '__main__':
    curio.run(main())
  1. Using a timeout with a task:
import curio

async def slow_operation():
    await curio.sleep(10)
    return 'Done'

async def main():
    try:
        result = await curio.timeout_after(5, slow_operation())
    except curio.TaskTimeout:
        print('Operation timed out')
    else:
        print(result)

curio.run(main())
  1. Working with queues:
import curio

async def producer(queue):
    for i in range(10):
        await queue.put(i)
    await queue.join()

async def consumer(queue):
    while True:
        item = await queue.get()
        print(f'Consumed: {item}')
        await queue.task_done()

async def main():
    queue = curio.Queue()
    await curio.gather([producer(queue), consumer(queue)])

curio.run(main())

Getting Started

To get started with Curio, first install it using pip:

pip install curio

Then, you can create a simple asynchronous program:

import curio

async def hello(name):
    await curio.sleep(1)
    print(f'Hello, {name}!')

async def main():
    await curio.gather([hello('Alice'), hello('Bob'), hello('Charlie')])

if __name__ == '__main__':
    curio.run(main())

This example demonstrates creating multiple concurrent tasks and running them using Curio's gather function.

Competitor Comparisons

15,061

Asynchronous HTTP client/server framework for asyncio and Python

Pros of aiohttp

  • More mature and widely adopted in the Python community
  • Comprehensive HTTP client and server functionality
  • Extensive documentation and community support

Cons of aiohttp

  • Larger codebase and more dependencies
  • Steeper learning curve for beginners
  • Potentially higher memory footprint

Code Comparison

aiohttp example:

async with aiohttp.ClientSession() as session:
    async with session.get('http://example.com') as response:
        html = await response.text()
        print(html)

Curio example:

async with curio.tcp_client('example.com', 80) as client:
    await client.sendall(b'GET / HTTP/1.0\r\nHost: example.com\r\n\r\n')
    response = await client.recv(10000)
    print(response.decode())

Key Differences

  • aiohttp provides a higher-level API for HTTP operations
  • Curio focuses on general-purpose async programming with a simpler core
  • aiohttp has more built-in features for web development
  • Curio requires more manual implementation for HTTP-specific tasks

Use Cases

  • aiohttp: Web applications, API clients, and servers
  • Curio: Low-level networking, custom async protocols, educational purposes

Community and Ecosystem

  • aiohttp has a larger ecosystem of extensions and plugins
  • Curio has a smaller but dedicated community focused on simplicity
6,145

Trio – a friendly Python library for async concurrency and I/O

Pros of Trio

  • More comprehensive documentation and tutorials
  • Larger community and ecosystem of third-party libraries
  • Built-in support for structured concurrency

Cons of Trio

  • Slightly more complex API compared to Curio
  • Steeper learning curve for beginners
  • May have slightly higher overhead in some scenarios

Code Comparison

Curio example:

import curio

async def hello():
    print('Hello, World!')

curio.run(hello)

Trio example:

import trio

async def hello():
    print('Hello, World!')

trio.run(hello)

Both Curio and Trio are asynchronous I/O libraries for Python, aiming to simplify concurrent programming. They share similar syntax and concepts, but Trio offers more features and a larger ecosystem. Curio, on the other hand, has a simpler API and may be easier for beginners to grasp initially.

Trio's structured concurrency model provides better control over task lifetimes and error propagation, while Curio relies more on traditional exception handling. Trio also offers more advanced features like cancellation scopes and nurseries.

In terms of performance, both libraries are generally comparable, with slight differences depending on the specific use case. Curio may have a slight edge in some scenarios due to its simpler implementation.

Ultimately, the choice between Curio and Trio depends on project requirements, team expertise, and desired features.

10,269

Ultra fast asyncio event loop.

Pros of uvloop

  • Higher performance due to Cython implementation and optimized event loop
  • Drop-in replacement for asyncio, making it easy to integrate into existing projects
  • Supports a wider range of networking protocols and features

Cons of uvloop

  • More complex codebase, potentially making it harder to contribute or understand internals
  • Requires compilation, which can be an issue in some deployment scenarios
  • May introduce platform-specific dependencies or limitations

Code Comparison

uvloop:

import uvloop
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
asyncio.run(main())

curio:

import curio
curio.run(main)

Key Differences

  • uvloop focuses on performance optimization for asyncio, while curio provides an alternative async framework
  • curio has a simpler, more Pythonic API compared to uvloop's asyncio-compatible interface
  • uvloop is better suited for high-performance network applications, while curio excels in readability and ease of use

Use Cases

  • Choose uvloop for projects requiring maximum performance within the asyncio ecosystem
  • Opt for curio when prioritizing code simplicity and maintainability in async programming

Both libraries offer valuable solutions for asynchronous programming in Python, with uvloop emphasizing performance and curio focusing on simplicity and readability.

10,027

The little ASGI framework that shines. 🌟

Pros of Starlette

  • More comprehensive web framework with built-in routing, middleware, and templating
  • Better suited for building full-featured web applications
  • Larger community and ecosystem, with more third-party extensions

Cons of Starlette

  • Heavier and more complex than Curio's minimalist approach
  • May have a steeper learning curve for beginners
  • Less focus on pure concurrency primitives

Code Comparison

Starlette:

from starlette.applications import Starlette
from starlette.responses import JSONResponse
from starlette.routing import Route

async def homepage(request):
    return JSONResponse({"message": "Hello, World!"})

app = Starlette(routes=[Route("/", homepage)])

Curio:

from curio import run, spawn
from curio.socket import *

async def echo_server(address):
    sock = await create_server(address)
    async with sock:
        while True:
            client, addr = await sock.accept()
            await spawn(echo_client, client, addr)

run(echo_server, ('', 25000))

Starlette is more focused on web application development, providing a higher-level API for routing and request handling. Curio, on the other hand, offers lower-level concurrency primitives and is better suited for building network servers and protocols from scratch.

75,446

FastAPI framework, high performance, easy to learn, fast to code, ready for production

Pros of FastAPI

  • Extensive documentation and large community support
  • Built-in support for OpenAPI (Swagger) and JSON Schema
  • High performance due to Starlette and Pydantic integration

Cons of FastAPI

  • Steeper learning curve for beginners due to type hinting and dependency injection
  • Heavier framework with more dependencies compared to Curio's minimalist approach

Code Comparison

FastAPI example:

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def root():
    return {"message": "Hello World"}

Curio example:

from curio import run, tcp_server

async def echo_server(client, addr):
    while True:
        data = await client.recv(1000)
        if not data:
            break
        await client.send(data)
    await client.close()

run(tcp_server, '', 25000, echo_server)

FastAPI is a modern, fast web framework for building APIs with Python 3.6+ based on standard Python type hints. It's designed for ease of use and high performance. Curio, on the other hand, is a library for writing concurrent network applications using Python coroutines with a focus on simplicity and clarity. While FastAPI is specifically tailored for building APIs, Curio provides a more general-purpose concurrency toolkit for various network programming tasks.

21,707

Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed.

Pros of Tornado

  • Mature and battle-tested framework with a large user base
  • Extensive documentation and community support
  • Built-in support for WebSockets and long polling

Cons of Tornado

  • More complex API compared to Curio's simpler design
  • Heavier footprint and slower performance in some scenarios
  • Less focus on modern Python features like async/await syntax

Code Comparison

Tornado example:

class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("Hello, World!")

app = tornado.web.Application([(r"/", MainHandler)])
app.listen(8888)
tornado.ioloop.IOLoop.current().start()

Curio example:

from curio import run, tcp_server

async def echo_server(client, addr):
    while True:
        data = await client.recv(1000)
        if not data:
            break
        await client.send(data)

run(tcp_server, '', 25000, echo_server)

Tornado offers a more traditional web framework approach, while Curio focuses on providing a lightweight, high-performance async I/O library. Tornado's API is more comprehensive, but Curio's simplicity and modern Python features make it attractive for certain use cases. The choice between the two depends on project requirements, performance needs, and developer preferences.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

Curio

Curio is a coroutine-based library for concurrent Python systems programming using async/await. It provides standard programming abstractions such as tasks, sockets, files, locks, and queues as well as some advanced features such as support for structured concurrency. It works on Unix and Windows and has zero dependencies. You'll find it to be familiar, small, fast, and fun.

Important Notice: October 25, 2022

The Curio project is no longer making package releases. I'm more than happy to accept bug reports and may continue to work on it from time to time as the mood strikes. If you want the absolute latest version, you should vendor the source code from here. Curio has no dependencies other than the Python standard library. --Dave

Curio is Different

One of the most important ideas from software architecture is the "separation of concerns." This can take many forms such as utilizing abstraction layers, object oriented programming, aspects, higher-order functions, and so forth. However, another effective form of it exists in the idea of separating execution environments. For example, "user mode" versus "kernel mode" in operating systems. This is the underlying idea in Curio, but applied to "asynchronous" versus "synchronous" execution.

A fundamental problem with asynchronous code is that it involves a completely different evaluation model that doesn't compose well with ordinary applications or with other approaches to concurrency such as thread programing. Although the addition of "async/await" to Python helps clarify such code, "async" libraries still tend to be a confused mess of functionality that mix asynchronous and synchronous functionality together in the same environment--often bolting it all together with an assortment of hacks that try to sort out all of associated API confusion.

Curio strictly separates asynchronous code from synchronous code. Specifically, all functionality related to the asynchronous environment utilizes "async/await" features and syntax--without exception. Moreover, interactions between async and sync code is carefully managed through a small set of simple mechanisms such as events and queues. As a result, Curio is small, fast, and significantly easier to reason about.

A Simple Example

Here is a concurrent TCP echo server directly implemented using sockets:

.. code:: python

# echoserv.py

from curio import run, spawn
from curio.socket import *

async def echo_server(address):
    sock = socket(AF_INET, SOCK_STREAM)
    sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
    sock.bind(address)
    sock.listen(5)
    print('Server listening at', address)
    async with sock:
        while True:
            client, addr = await sock.accept()
            await spawn(echo_client, client, addr, daemon=True)

async def echo_client(client, addr):
    print('Connection from', addr)
    async with client:
         while True:
             data = await client.recv(100000)
             if not data:
                 break
             await client.sendall(data)
    print('Connection closed')

if __name__ == '__main__':
    run(echo_server, ('',25000))

If you've done network programming with threads, it looks almost identical. Moreover, it can handle thousands of clients even though no threads are being used inside.

Core Features

Curio supports standard synchronization primitives (events, locks, recursive locks, semaphores, and condition variables), queues, subprocesses, as well as running tasks in threads and processes. The task model fully supports cancellation, task groups, timeouts, monitoring, and other features critical to writing reliable code.

Read the official documentation <https://curio.readthedocs.io>_ for more in-depth coverage. The tutorial <https://curio.readthedocs.io/en/latest/tutorial.html>_ is a good starting point. The howto <https://curio.readthedocs.io/en/latest/howto.html>_ describes how to carry out common programming tasks.

Talks Related to Curio

Concepts related to Curio's design and general issues related to async programming have been described by Curio's creator, David Beazley <https://www.dabeaz.com>_, in various conference talks and tutorials:

  • Build Your Own Async <https://www.youtube.com/watch?v=Y4Gt3Xjd7G8>_, Workshop talk by David Beazley at PyCon India, 2019.

  • The Other Async (Threads + Asyncio = Love) <https://www.youtube.com/watch?v=x1ndXuw7S0s>_, Keynote talk by David Beazley at PyGotham, 2017.

  • Fear and Awaiting in Async <https://www.youtube.com/watch?v=E-1Y4kSsAFc>_, Keynote talk by David Beazley at PyOhio 2016.

  • Topics of Interest (Async) <https://www.youtube.com/watch?v=ZzfHjytDceU>_, Keynote talk by David Beazley at Python Brasil 2015.

  • Python Concurrency from the Ground Up (LIVE) <https://www.youtube.com/watch?v=MCs5OvhV9S4>_, talk by David Beazley at PyCon 2015.

Questions and Answers

Q: What is the point of the Curio project?

A: Curio is async programming, reimagined as something smaller, faster, and easier to reason about. It is meant to be both educational and practical.

Q: Is Curio implemented using asyncio?

A: No. Curio is a standalone library directly created from low-level I/O primitives.

Q: Is Curio meant to be a clone of asyncio?

A: No. Although Curio provides a significant amount of overlapping functionality, the API is different. Compatibility with other libaries is not a goal.

Q: Is Curio meant to be compatible with other async libraries?

A: No. Curio is a stand-alone project that emphasizes a certain software architecture based on separation of environments. Other libraries have largely ignored this concept, preferring to simply provide variations on the existing approach found in asyncio.

Q: Can Curio interoperate with other event loops?

A: It depends on what you mean by the word "interoperate." Curio's preferred mechanism of communication with the external world is a queue. It is possible to communicate between Curio, threads, and other event loops using queues.

Q: How fast is Curio?

A: Curio's primary goal is to be an async library that is minimal and understandable. Performance is not the primary concern. That said, in rough benchmarking of a simple echo server, Curio is more than twice as fast as comparable code using coroutines in asyncio or trio. This was last measured on OS-X using Python 3.9. Keep in mind there is a lot more to overall application performance than the performance of a simple echo server so your mileage might vary. However, as a runtime environment, Curio doesn't introduce a lot of extra overhead. See the examples/benchmark directory for various testing programs.

Q: What is the future of Curio?

A: Curio should be viewed as a library of basic programming primitives. At this time, it is considered to be feature-complete--meaning that it is not expected to sprout many new capabilities. It may be updated from time to time to fix bugs or support new versions of Python.

Q: Can I contribute?

A: Curio is not a community-based project seeking developers or maintainers. However, having it work reliably is important. If you've found a bug or have an idea for making it better, please file an issue <https://github.com/dabeaz/curio>_.

Contributors

The following people contributed ideas to early stages of the Curio project: Brett Cannon, Nathaniel Smith, Alexander Zhukov, Laura Dickinson, and Sandeep Gupta.

Who

Curio is the creation of David Beazley (@dabeaz) who is also responsible for its maintenance. http://www.dabeaz.com

P.S.

If you want to learn more about concurrent programming more generally, you should come take a course <https://www.dabeaz.com/courses.html>_!

.. |--| unicode:: U+2013 .. en dash .. |---| unicode:: U+2014 .. em dash, trimming surrounding whitespace :trim: