File size: 5,192 Bytes
e0d6c83
 
 
 
 
871b360
8861b68
871b360
e0d6c83
871b360
e0d6c83
 
871b360
 
e0d6c83
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
871b360
 
 
 
e0d6c83
 
871b360
 
 
 
e0d6c83
 
871b360
 
 
 
e0d6c83
 
871b360
 
 
 
e0d6c83
 
 
 
 
871b360
e0d6c83
871b360
 
 
e0d6c83
 
 
 
871b360
 
 
 
 
 
 
e0d6c83
871b360
 
 
 
 
 
 
e0d6c83
 
 
 
 
871b360
 
e0d6c83
871b360
 
 
 
 
 
e0d6c83
 
 
871b360
 
e0d6c83
 
871b360
e0d6c83
871b360
e0d6c83
 
 
 
871b360
 
 
 
27a8ca5
e0d6c83
871b360
 
 
 
e0d6c83
 
 
871b360
 
e0d6c83
871b360
 
 
 
 
 
 
 
 
 
 
 
 
 
e0d6c83
 
 
 
 
 
871b360
 
e0d6c83
871b360
 
e0d6c83
 
 
 
871b360
 
 
 
e0d6c83
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
import logging
import random
import time

import gradio as gr
from tqdm import tqdm

from gradio_logsview import LogsView, LogsViewRunner

logger = logging.getLogger("custom.foo")

def random_values(failing: bool = False):
    for i in tqdm(range(10)):
        logger.log(
            random.choice(
                [  # Random levels
                    logging.INFO,
                    logging.DEBUG,
                    logging.WARNING,
                    logging.ERROR,
                    logging.CRITICAL,
                ]
            ),
            f"Value {i+1}",  # Random values
        )
        time.sleep(random.uniform(0, 1))
        if failing and i == 5:
            raise ValueError("Failing!!")


def fn_command_success():
    runner = LogsViewRunner()
    yield from runner.run_command(["python", "-u", "demo/script.py"])
    yield runner.log(f"Runner: {runner}")


def fn_command_failing():
    runner = LogsViewRunner()
    yield from runner.run_command(["python", "-u", "demo/script.py", "--failing"])
    yield runner.log(f"Runner: {runner}")


def fn_python_success():
    runner = LogsViewRunner()
    yield from runner.run_python(random_values, log_level=logging.INFO, logger_name="custom.foo", failing=False)
    yield runner.log(f"Runner: {runner}")


def fn_python_failing():
    runner = LogsViewRunner()
    yield from runner.run_python(random_values, log_level=logging.INFO, logger_name="custom.foo", failing=True)
    yield runner.log(f"Runner: {runner}")


markdown_top = """
# LogsView Demo

This demo shows how to use the `LogsView` component to run some Python code or execute a command and display logs in real-time.

Click on any button to launch a process and see the logs displayed in real-time.
In the Python examples, code is executed in a process. You can see the logs (generated randomly with different log levels).
In the command examples, the command line is executed on the system directly. Any command can be executed.
"""


markdown_bottom = """
## Installation

```
pip install https://huggingface.co/spaces/Wauplin/gradio_logsview/resolve/main/gradio_logsview-0.0.5-py3-none-any.whl
```

or add this line to your `requirements.txt`:

```
gradio_logsview@https://huggingface.co/spaces/Wauplin/gradio_logsview/resolve/main/gradio_logsview-0.0.5-py3-none-any.whl
```

## How to run Python code?

With `LogsView.run_python`, you can run Python code in a separate process and capture logs in real-time.
You can configure which logs to capture (log level and logger name).

```py
from gradio_logsview import LogsView

def fn_python():
    # Run `my_function` in a separate process
    # All logs above `INFO` level will be captured and displayed in real-time.
    runner = LogsViewRunner() # Initialize the runner
    yield from runner.run_python(my_function, log_level=logging.INFO, arg1="value1")
    yield runner.log(f"Runner: {runner}") # Log any message
    if runner.exit_code != 0:
        # Handle error
        ...

with gr.Blocks() as demo:
    logs = LogsView()
    btn = gr.Button("Run Python code")
    btn.click(fn_python, outputs=logs)
```

## How to run a command?

With `LogsView.run_command`, you can run a command on the system and capture logs from the process in real-time.
    
```py
from gradio_logsview import LogsView

def fn_command():
    # Run a command and capture all logs from the subprocess
    runner = LogsViewRunner() # Initialize the runner
    yield from runner.run_command(
        ["mergekit-yaml", "config.yaml", "merge", "--copy-", "--cuda", "--low-cpu-memory"]
    )
    yield runner.log(f"Runner: {runner}") # Log any message
    if runner.exit_code != 0:
        # Handle error
        ...

with gr.Blocks() as demo:
    logs = LogsView()
    btn = gr.Button("Run command")
    btn.click(fn_command, outputs=logs)
```

## TODO

- [ ] display logs with colors (front-end)
- [ ] format logs client-side (front-end)
- [ ] scrollable logs if more than N lines (front-end)
- [ ] format each log only once (front-end)
- [x] stop process if `run_command` gets cancelled (back-end)
- [x] correctly pass error stacktrace in `run_python` (back-end)
- [x] correctly catch print statements in `run_python` (back-end)
- [ ] disable interactivity + remove all code editing logic (both?)
- [x] how to handle progress bars? (i.e when logs are overwritten in terminal)
- [ ] Have 3 tabs in UI for stdout, stderr and logging (front-end + back-end)
- [ ] Write logger name in the logs (back-end)
"""

with gr.Blocks() as demo:
    gr.Markdown(markdown_top)

    with gr.Row():
        btn_python_success = gr.Button("Run Python code (success)")
        btn_python_failing = gr.Button("Run Python code (failing)")
    with gr.Row():
        btn_command_success = gr.Button("Run command (success)")
        btn_command_failing = gr.Button("Run command (failing)")
    logs = LogsView()

    gr.Markdown(markdown_bottom)

    btn_python_failing.click(fn_python_failing, outputs=logs)
    btn_python_success.click(fn_python_success, outputs=logs)
    btn_command_failing.click(fn_command_failing, outputs=logs)
    btn_command_success.click(fn_command_success, outputs=logs)


if __name__ == "__main__":
    demo.launch()