Skip to main content

PyQt/PySide interface to handle logging data to file particularly well suited for multithreaded programs.

Project description

https://img.shields.io/pypi/v/dvg-pyqt-filelogger https://img.shields.io/pypi/pyversions/dvg-pyqt-filelogger https://img.shields.io/badge/code%20style-black-000000.svg https://img.shields.io/badge/License-MIT-purple.svg

DvG_PyQt_FileLogger

PyQt/PySide interface to handle logging data to file particularly well suited for multithreaded programs.

Supports PyQt5, PyQt6, PySide2 and PySide6.

Installation:

pip install dvg-pyqt-filelogger

API

class FileLogger(write_header_function: Callable = None, write_data_function: Callable = None)

Bases: PyQt5.QtCore.QObject

Handles logging data to a file particularly well suited for multithreaded programs where one thread is writing data to the log and the other thread (the main/GUI thread) requests starting and stopping of the log, e.g., by the user pressing a button.

The methods start_recording(), stop_recording() and record(bool) can be directly called from the main/GUI thread.

In the logging thread you repeatedly need to call update(). This method takes cares of the state machine behind FileLogger and will perform the appropiate action, such as creating a file on disk, creating the header or writing new data to the log.

Args:
write_header_function (Callable, optional):

Reference to a function that contains your specific code to write a header to the log file. This will get called during update().

Default: None

write_data_function (Callable, optional):

Reference to a function that contains your specific code to write new data to the log file. This will get called during update().

Default: None

Both of the above functions can contain calls to the following class members:

  • FileLogger.write()

  • FileLogger.elapsed()

NOTE:

This class lacks a mutex and is hence not threadsafe from the get-go. As long as update() is being called from inside another mutex, such as a data-acquisition mutex for instance, it is safe.

NOTE:

By design the code in this class will continue on when exceptions occur. They are reported to the command line.

Signals:

signal_recording_started (str):

Emitted whenever a new recording has started. Useful for, e.g., updating text of a record button.

Returns:

The filepath as str of the newly created log file.

Type:

PyQt5.QtCore.pyqtSignal()

signal_recording_stopped (pathlib.Path):

Emitted whenever the recording has stopped. Useful for, e.g., updating text of a record button.

Returns:

The filepath as pathlib.Path() of the newly created log file. You could use this to, e.g., automatically navigate to the log in the file explorer or ask the user for a ‘save to’ destination.

Type:

PyQt5.QtCore.pyqtSignal()

Example usage:

from PyQt5 import QtWidgets as QtWid
from dvg_pyqt_filelogger import FileLogger

#  When using a PyQt5 GUI put this inside your ``MainWindow()`` definition:
# ----

self.qpbt_record = QtWid.QPushButton(
    text="Click to start recording to file",
    checkable=True
)
self.qpbt_record.clicked.connect(lambda state: log.record(state))

#  Initialize FileLogger at __main__
# ----

window = MainWindow()

log = FileLogger(
    write_header_function=write_header_to_log,
    write_data_function=write_data_to_log
)
log.signal_recording_started.connect(
    lambda filepath: window.qpbt_record.setText(
        "Recording to file: %s" % filepath
    )
)
log.signal_recording_stopped.connect(
    lambda: window.qpbt_record.setText(
        "Click to start recording to file"
    )
)

#  Define these functions in your main module:
# ----

def write_header_to_log():
    log.write("elapsed [s]\treading_1\n")

def write_data_to_log():
    log.write("%.3f\t%.4f\n" % (log.elapsed(), state.reading_1))

#  Lastly, put this inside your logging thread:
# ----

log.update()

Methods

  • set_write_header_function(write_header_function: Callable)

  • set_write_data_function(write_data_function: Callable)

  • record(state: bool = True)

    Can be called from any thread.

  • start_recording()

    Can be called from any thread.

  • stop_recording()

    Can be called from any thread.

  • update(filepath: str = "", mode: str = "a")

    This method will have to get called repeatedly, presumably in the thread where logging is required, e.g., the data-generation thread. This method takes cares of the state machine behind FileLogger and will perform the appropriate action, such as creating a file on disk, creating the header or writing new data to the log.

    Args:
    filepath (str):

    Location of the log file in case it has to be created or opened for write access.

    Default: "{yyMMdd_HHmmss}.txt" denoting the current date and time.

    mode (str, optional):

    Mode in which the log file is to be opened, see open() for more details. Most common options:

    • w: Open for writing, truncating the file first.

    • a: Open for writing, appending to the end of the file if it exists.

    Defaults: a

  • write(data: AnyStr) -> bool

    Write binary or ASCII data to the currently opened log file. By design any exceptions occurring in this method will not terminate the execution, but it will report the error to the command line and continue on instead.

    Returns True if successful, False otherwise.

  • np_savetxt(*args, **kwargs) -> bool

    Write 1D or 2D array_like data to the currently opened log file. This method passes all arguments directly to numpy.savetxt(), see https://numpy.org/doc/stable/reference/generated/numpy.savetxt.html. This method outperforms FileLogger.write(), especially when large chunks of 2D data are passed (my test shows 8x faster).

    By design any exceptions occurring in this method will not terminate the execution, but it will report the error to the command line and continue on instead.

    Returns True if successful, False otherwise.

  • flush()

    Force-flush the contents in the OS buffer to file as soon as possible. Do not call repeatedly, because it causes overhead.

  • close()

  • is_recording() -> bool

  • elapsed() -> float

    Returns time in seconds (float) since start of recording.

  • pretty_elapsed() -> str

    Returns time as “h:mm:ss” (str) since start of recording.

Changelog

1.3.0 (2023-02-27)

  • Raise ImportError instead of general Exception

1.2.0 (2022-09-13)

  • Added support for PyQt5, PyQt6, PySide2 and PySide6

1.1.0 (2021-05-13)

  • Added support for numpy.savetxt()

1.0.0 (2020-08-11)

  • First release on PyPI

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dvg-pyqt-filelogger-1.3.0.tar.gz (7.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dvg_pyqt_filelogger-1.3.0-py3-none-any.whl (9.3 kB view details)

Uploaded Python 3

File details

Details for the file dvg-pyqt-filelogger-1.3.0.tar.gz.

File metadata

  • Download URL: dvg-pyqt-filelogger-1.3.0.tar.gz
  • Upload date:
  • Size: 7.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.10.9

File hashes

Hashes for dvg-pyqt-filelogger-1.3.0.tar.gz
Algorithm Hash digest
SHA256 08b3654dbbdd9271b1bb914481267f2d93044fb651293836f6c1b2b9b1c3209e
MD5 5d36360e9e4b7d0ecb4ec2c25e40b331
BLAKE2b-256 43fef8d03c685ee0ccbf04a9e32fc1364f5ce6dd10a6141289711c613395475e

See more details on using hashes here.

File details

Details for the file dvg_pyqt_filelogger-1.3.0-py3-none-any.whl.

File metadata

File hashes

Hashes for dvg_pyqt_filelogger-1.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ae1f29ec893f50f6eba999c901447daf1cf8b6d04534fbb3442547af196ef562
MD5 f66390ad2c9510a3860c63851cb8f60e
BLAKE2b-256 d73ca601ce39f33e8a1c1e4bb492008a507c8ad560cc5140ec5b475b2e27eda2

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page