Giter Site home page Giter Site logo

multiplex's Introduction

multiplex

View output of multiple processes, in parallel, in the console, with an interactive TUI

Installation

pip install multiplex
# or better yet
pipx install multiplex

Python 3.7 or greater is required.

Examples

Parallel Execution Of Commands

mp \
    './some-long-running-process.py --zone z1' \
    './some-long-running-process.py --zone z2' \
    './some-long-running-process.py --zone z3'

Par

You can achive the same effect using Python API like this:

from multiplex import Multiplex

mp = Multiplex()
for zone in ['z1', 'z2', 'z3']:
    mp.add(f"./some-long-running-process.py --zone {zone}")
mp.run()

Dynamically Add Commands

my-script.sh:

#!/bin/bash -e
echo Hello There

export REPO='[email protected]:dankilman/multiplex.git'

mp 'git clone $REPO'
mp 'pyenv virtualenv 3.8.5 multiplex-demo && pyenv local multiplex-demo'
cd multiplex
mp 'poetry install'
mp 'pytest tests'

mp @ Goodbye -b 0

And then running:

mp ./my-script.sh -b 7

Seq

Python Controller

An output similar to the first example can be achieved from a single process using the Python Controller API.

import random
import time
import threading

from multiplex import Multiplex, Controller

CSI = "\033["
RESET = CSI + "0m"
RED = CSI + "31m"
GREEN = CSI + "32m"
BLUE = CSI + "34m"
MAG = CSI + "35m"
CYAN = CSI + "36m"

mp = Multiplex()

controllers = [Controller(f"zone z{i+1}", thread_safe=True) for i in range(3)]

for controller in controllers:
    mp.add(controller)

def run(index, c):
    c.write(
        f"Starting long running process in zone {BLUE}z{index}{RESET}, "
        f"that is not really long for demo purposes\n"
    )
    count1 = count2 = 0
    while True:
        count1 += random.randint(0, 1000)
        count2 += random.randint(0, 1000)
        sleep = random.random() * 3
        time.sleep(sleep)
        c.write(
            f"Processed {RED}{count1}{RESET} orders, "
            f"total amount: {GREEN}${count2}{RESET}, "
            f"Time it took to process this batch: {MAG}{sleep:0.2f}s{RESET}, "
            f"Some more random data: {CYAN}{random.randint(500, 600)}{RESET}\n"
        )

for index, controller in enumerate(controllers):
    thread = threading.Thread(target=run, args=(index+1, controller))
    thread.daemon = True
    thread.start()

mp.run()

Cont

Help Screen

Type ? to toggle the help screen.

help

Why Not Tmux?

In short, they solve different problems.

tmux is a full blown terminal emulator multiplexer. multiplex on the other hand, tries to optimize for a smooth experience in navigating output from several sources.

tmux doesn't have any notion of scrolling panes. That is to say, the layout contains all panes at any given moment (unless maximized). In multiplex, current view will display boxes that fit current view, but you can have many more, and move around boxes using less inspired keys such as j, k, g, G, etc...

Another aspect is that keybindigs for moving around are much more ergonomic (as they are in less) because multiplex is not a full terminal emulator, so it can afford using single letter keyboard bindings (e.g. g for go to beginning)

multiplex's People

Contributors

conradludgate avatar dankilman avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

multiplex's Issues

multiplex chokes on byte 0xe2?

Strangely, there seems to be an issue handling this byte stream hotplug-autorun.without-multiplex.log, it results in this error:

Traceback (most recent call last):
  File "/mnt/stix/usb-live-linux/scripts/hotplug-autorun", line 193, in <module>
    main()
  File "/mnt/stix/usb-live-linux/scripts/hotplug-autorun", line 181, in main
    mp.run()
  File "/usr/lib/python3/dist-packages/multiplex/multiplex.py", line 25, in run
Loop <_UnixSelectorEventLoop running=False closed=True debug=False> that handles pid 583160 is closed
    asyncio.run(self.run_async(load))
  File "/usr/lib/python3.10/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/usr/lib/python3.10/asyncio/base_events.py", line 646, in run_until_complete
    return future.result()
  File "/usr/lib/python3/dist-packages/multiplex/multiplex.py", line 46, in run_async
    await self.viewer.run()
  File "/usr/lib/python3/dist-packages/multiplex/viewer.py", line 186, in run
    await self._main()
  File "/usr/lib/python3/dist-packages/multiplex/viewer.py", line 208, in _main
    async for obj, output in streamer:
  File "/usr/lib/python3/dist-packages/aiostream/stream/advanced.py", line 59, in base_combine
    result = task.result()
  File "/usr/lib/python3/dist-packages/multiplex/viewer.py", line 270, in _wrapped_iterator
    async for elem in iterator:
  File "/usr/lib/python3/dist-packages/multiplex/iterator.py", line 200, in g
    async for data in s:
  File "/usr/lib/python3/dist-packages/aiostream/stream/advanced.py", line 59, in base_combine
    result = task.result()
  File "/usr/lib/python3/dist-packages/multiplex/iterator.py", line 34, in stream_reader_generator
    yield b.decode()
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe2 in position 5034: unexpected end of data

Any idea? ๐Ÿค”

Add buffer limit

Currently buffer has not limit and can grow indefinitely. This may be an issue in some long running processes.

Add search capabilites

Currently, in order to search content, one needs to dump content using Shift-O which is not optimal

Consider a basic form of input

Full blown input would be an overkill and would certainly be better served by tmux.
This should address basic cases with prompts such as: do you want to continue: [y/n] and alike

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.