pynnex

PynneX

PynneX is a lightweight, pure-Python emitter-listener (signal-slot) library that provides thread-safe, asyncio-compatible event handling. It enables clean decoupling of components, seamless thread-to-thread communication, and flexible asynchronous/synchronous listener handling. If you prefer Qt-style naming, signal-slot aliases are also available, as well as publisher-subscriber for a Pub/Sub feel.

Key Features

Why PynneX?

Modern Python applications often combine asynchronous operations and multithreading. Many event-driven frameworks come with large dependencies or limited async/thread support. PynneX aims to fill the gap by offering:

Key Benefits

Async-Ready

Thread-Safe by Design

Flexible Listeners

Robust Testing & Examples

Installation

PynneX requires Python 3.10+ for stable asyncio operations:

git clone https://github.com/nexconnectio/pynnex.git
cd pynnex
pip install -e .

For development (includes tests and linting tools):

pip install -e ".[dev]"

Quick Start

Basic Example

from pynnex import with_emitters, emitter, listener

@with_emitters
class Counter:
    def __init__(self):
        self.count = 0
    
    @emitter
    def count_changed(self):
        pass
    
    def increment(self):
        self.count += 1
        self.count_changed.emit(self.count)

@with_emitters
class Display:
    @listener
    async def on_count_changed(self, value):
        print(f"Count is now: {value}")

# Connect and use
counter = Counter()
display = Display()
counter.count_changed.connect(display, display.on_count_changed)
counter.increment()  # Will print: "Count is now: 1"

Asynchronous Listener Example

@with_emitters
class AsyncDisplay:
    @listener
    async def on_count_changed(self, value):
        await asyncio.sleep(1)  # Simulate async operation
        print(f"Count updated to: {value}")

# Usage in async context
async def main():
    counter = Counter()
    display = AsyncDisplay()
    
    counter.count_changed.connect(display, display.on_count_changed)
    counter.increment()
    
    # Wait for async processing
    await asyncio.sleep(1.1)

asyncio.run(main())

Core Concepts

Emitters and Listeners (Signal/Slot Aliases Available)

Thread Safety and Connection Types

PynneX detects whether the emitter call and listener execution happen in the same thread or different ones:

Worker Threads

For background work, PynneX provides a @nx_with_worker(alias @with_worker) decorator that:

** Worker Example **

from pynnex import with_worker, emitter

@with_worker
class DataProcessor:
    @emitter
    def processing_done(self):
        pass

    async def run(self, *args, **kwargs):
        # The main entry point for the worker thread’s event loop
        # Wait for tasks or stopping signal
        await self.wait_for_stop()

    async def process_data(self, data):
        # Perform heavy computation in the worker thread
        result = await heavy_computation(data)
        self.processing_done.emit(result)

processor = DataProcessor()
processor.start()

# Queue a task to run in the worker thread:
processor.queue_task(processor.process_data(some_data))

# Stop the worker gracefully
processor.stop()

From Basics to Practical Use Cases

We’ve expanded PynneX’s examples to guide you from simple demos to full-fledged applications. Each example has its own GitHub link with fully commented code.

For detailed explanations, code walkthroughs, and architecture diagrams of these examples, check out our Examples Documentation.

Basic Examples

Multi-Threading and Workers

Real-Time Stock Monitors (Console & GUI)

Stock Monitor Console

Stock Monitor Console: Real-time price updates, alert configuration, and notification history in action

Stock Monitor UI

Stock Monitor UI: Real-time price updates, alert configuration, and notification history in action

Documentation and Examples

Get Started

  1. Visit the GitHub Repository
  2. Install via pip install pynnex (Python 3.10+)
  3. Explore the examples and documentation for real-world use cases
  4. Contribute / Feedback: Check our Contributing Guidelines

License

PynneX is licensed under the MIT License. See LICENSE for details.