Metadata-Version: 2.4
Name: logcatter
Version: 0.4.0
Summary: Logcat style log library
Project-URL: Homepage, https://github.com/RivMt/logcatter
Project-URL: Issues, https://github.com/RivMt/logcatter/issues
Author-email: KANG SAN <san.kang@rivmt.com>
License-Expression: MIT
License-File: LICENSE
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Requires-Python: >=3.7
Requires-Dist: tqdm
Description-Content-Type: text/markdown

# Logcatter

Android Logcat-style logging for Python.

Logcatter provides a compact static API, automatic source-file tags, colored log
levels, exception and stack trace output, file logging, and multiprocessing
support without requiring a logging configuration file.

[View Logcatter on PyPI](https://pypi.org/project/logcatter/)

## Features

- **Logcat-style output** — Logs use the format
  `YYYY-MM-DD HH:mm:ss SSS [L/filename.py] message`.
- **Automatic source tags** — The filename that called `Log` is included in
  every entry, making the source of a message easy to identify.
- **Six log levels** — Use `Log.v()`, `Log.d()`, `Log.i()`, `Log.w()`,
  `Log.e()`, and `Log.f()` for verbose through fatal messages.
- **Colored console output** — Each severity is color-coded for quick scanning.
- **Runtime level filtering** — Change the minimum visible level with
  `Log.set_level()`.
- **Exception and stack traces** — Attach an exception with `e=` or include the
  current stack with `s=True`.
- **File logging** — Add a color-free file output with `Log.save()`.
- **Standard stream redirection** — Capture `print()` and writes to `stderr`
  inside a context manager.
- **Progress bars** — `Log.tqdm()` keeps log messages from overwriting active
  `tqdm` progress bars.
- **Multiprocessing support** — Route logs from worker processes through a
  shared listener, including `multiprocessing.Pool` and PyTorch `DataLoader`
  workers.

## Installation

```shell
pip install logcatter
```

Logcatter requires Python 3.7 or later.

## Quick start

Initialize Logcatter near the start of the program and dispose it before the
program exits so queued messages are flushed.

```python
from logcatter import Log

Log.init()

try:
    Log.d("Loading configuration")
    Log.i("Application started")

    Log.set_level(Log.WARNING)
    Log.i("This message is filtered out")
    Log.w("Only warnings and higher are now shown")

    try:
        raise ValueError("Invalid value")
    except ValueError as error:
        Log.e("Request failed", e=error)

    Log.f("Fatal error with the current stack", s=True)
finally:
    Log.dispose()
```

Available levels, from lowest to highest severity:

| Level | Method | Constant |
| --- | --- | --- |
| Verbose | `Log.v()` | `Log.VERBOSE` |
| Debug | `Log.d()` | `Log.DEBUG` |
| Info | `Log.i()` | `Log.INFO` |
| Warning | `Log.w()` | `Log.WARNING` |
| Error | `Log.e()` | `Log.ERROR` |
| Fatal | `Log.f()` | `Log.FATAL` |

Logging methods also support standard `logging`-style arguments:

```python
Log.i("Processed %d records", record_count)
```

## Redirect `stdout` and `stderr`

Use `Log.redirect()` to apply Logcatter formatting to code that writes with
`print()` or directly to a standard stream.

```python
import sys

from logcatter import Log

Log.init()

try:
    with Log.redirect(stdout=Log.INFO, stderr=Log.ERROR):
        print("Captured as an INFO message")
        sys.stderr.write("Captured as an ERROR message\n")
finally:
    Log.dispose()
```

Set either argument to `None` to leave that stream unchanged. The defaults
redirect `stdout` at `VERBOSE` level and leave `stderr` unchanged.

Output that uses carriage returns to redraw the current line is not reformatted.
For progress bars, use `Log.tqdm()` instead.

## Use with `tqdm`

`Log.tqdm()` accepts the same arguments as `tqdm.tqdm` and prevents log entries
from being appended to the progress-bar line.

```python
from logcatter import Log

Log.init()

try:
    for item in Log.tqdm(items, desc="Processing"):
        Log.i("Processing %s", item)
finally:
    Log.dispose()
```

It can also be used as a context manager for manual progress updates.

## Save logs to a file

Call `Log.save()` to add a file handler. File output uses the same Logcat-style
format without ANSI color codes.

```python
from logcatter import Log

Log.init()
Log.save("application.log")

try:
    Log.i("Written to both the console and application.log")
finally:
    Log.dispose()
```

The default mode is `"w"`. Pass `mode="a"` to append instead:

```python
Log.save("application.log", mode="a")
```

## Multiprocessing

Call `Log.init()` in the main process, then use the callable returned by
`Log.init_worker()` as the pool initializer. Keep the entry-point guard when
using `multiprocessing`.

```python
import multiprocessing

from logcatter import Log


def process_item(item):
    Log.i("Processing %s", item)


if __name__ == "__main__":
    Log.init()

    try:
        with multiprocessing.Pool(
            processes=2,
            initializer=Log.init_worker(),
        ) as pool:
            pool.map(process_item, range(4))
    finally:
        Log.dispose()
```

### PyTorch `DataLoader`

Pass `Log.init_worker()` to `worker_init_fn` so worker logs use the shared log
queue.

```python
from torch.utils.data import DataLoader

from logcatter import Log

Log.init()

train_loader = DataLoader(
    dataset,
    num_workers=4,
    worker_init_fn=Log.init_worker(),
)
```

Call `Log.dispose()` after the loader and its workers are no longer needed.

## Output examples

### Visual Studio Code

![Logcatter output in Visual Studio Code](docs/images/vsc.png)

### PyCharm

![Logcatter output in PyCharm](docs/images/pycharm.png)

### PowerShell 7 in Windows Terminal

![Logcatter output in PowerShell 7 on Windows Terminal](docs/images/powershell.png)

## License

Logcatter is available under the [MIT License](LICENSE).
