Organizátoři konference LinuxDays ukončili veřejné přihlašování přednášek. Teď je na vás, abyste vybrali nejlepší témata, která na letošní konferenci zaznějí. Hlasovat můžete do neděle 7. září. Poté podle výsledků hlasování organizátoři sestaví program pro letošní ročník. Konference proběhne 4. a 5. října v Praze.
Byla vydána verze 11.0.0 vizuálního programovacího jazyka Snap! (Wikipedie) inspirovaného jazykem Scratch (Wikipedie). Přehled novinek na GitHubu.
Na čem aktuálně pracují vývojáři GNOME a KDE Plasma? Pravidelný přehled novinek v Týden v GNOME a Týden v KDE Plasma. Vypíchnout lze, že v Plasmě byl implementován 22letý požadavek. Historie schránky nově umožňuje ohvězdičkovat vybrané položky a mít k ním trvalý a snadný přístup.
Wayfire, kompozitní správce oken běžící nad Waylandem a využívající wlroots, byl vydán ve verzi 0.10.0. Zdrojové kódy jsou k dispozici na GitHubu. Videoukázky na YouTube.
Před necelými čtyřmi měsíci byl Steven Deobald jmenován novým výkonným ředitelem GNOME Foundation. Včera skončil, protože "nebyl pro tuto roli v tento čas ten pravý".
Nové číslo časopisu Raspberry Pi zdarma ke čtení: Raspberry Pi Official Magazine 156 (pdf).
Armbian, tj. linuxová distribuce založená na Debianu a Ubuntu optimalizovaná pro jednodeskové počítače na platformě ARM a RISC-V, ke stažení ale také pro Intel a AMD, byl vydán ve verzi 25.8.1. Přehled novinek v Changelogu.
Včera večer měl na YouTube premiéru dokumentární film Python: The Documentary | An origin story.
Společnost comma.ai po třech letech od vydání verze 0.9 vydala novou verzi 0.10 open source pokročilého asistenčního systému pro řidiče openpilot (Wikipedie). Zdrojové kódy jsou k dispozici na GitHubu.
Ubuntu nově pro testování nových verzí vydává měsíční snapshoty. Dnes vyšel 4. snapshot Ubuntu 25.10 (Questing Quokka).
Hledal jsem možnost, jak sledovat logy, kreré vytváří python přes logger logging
. Programy tail
, more
a všechny ostatní metody nesplňovaly moje požadavky ( nebo neumím číst man
a google ).
Moje bádání v tomto směru bylo ukončeno rozhodnutím udělat takový program v Pythonu. Cesta (pro mně) síce zdlouhavější, zato však inspirativní.
(doufám, že se tady dozvím, že i zbytečná, protože tohle už přece dávno existuje a všichni to dobře vědí... kromě mně, tedy.)
Program jsem psal Pythonu + pySide2. Je jednoúčelový, hlídá jen jeden log, jednoho typu, ale plně funguje a navíc logy obarvuje. Ještě mě napadá dodělat pořádně otevírání souborů a barvení ANSI sekvencí, tak možná později, až na to bude čas...
Přikládám kód: Pro znovuotevření jiného souboru jsem plánoval odpojit a znovu připojit signál fileChanged (aby se nezdvojoval), ale nepovedlo se mi najít správnou kombinaci pro fuknci receivers .. nějak nevím čím ji nakrmit, no vyřešil jsem to jinak.
#! /usr/bin/python3
# This Python file uses the following encoding: utf-8
import sys
import os
from PySide2.QtWidgets import QApplication, QMainWindow
from PySide2.QtCore import QFile, Slot, Signal, SIGNAL, QFileSystemWatcher
from PySide2.QtUiTools import QUiLoader
class Reader(QMainWindow):
def __init__(self):
super(Reader, self).__init__()
self.load_ui()
self.fwatcher = QFileSystemWatcher()
self.fwatcher.fileChanged.connect(self.fileWasChanged)
def load_ui(self):
loader = QUiLoader()
path = os.path.join(os.path.dirname(__file__), "form.ui")
ui_file = QFile(path)
ui_file.open(QFile.ReadOnly)
self.ui = loader.load(ui_file)
ui_file.close()
self.ui.action_Open_file.triggered.connect(self.readFile)
self.ui.show()
@Slot()
def readFile(self):
# noConnection = self.fwatcher.receivers("filechanged")
watchedFiles = self.fwatcher.files()
if watchedFiles:
self.fwatcher.removePaths(watchedFiles)
self.fname = "/home/blabla/muj.log"
self.fwatcher.addPath(self.fname)
self.fillBrowser()
def fillBrowser(self):
content = ""
with open(self.fname, "r") as fh:
while True:
line = fh.readline()
if not line:
break
line = self.loggerConvert(line)
content += line
self.ui.textBrowser.setHtml(content)
@Slot(str)
def fileWasChanged(self, path):
self.fillBrowser()
def loggerConvert(self, line):
line = line.replace("NOTSET", '<font color="gray>NOTSET</font>')
line = line.replace("DEBUG", '<font color="blue">DEBUG</font>')
line = line.replace("INFO", '\
<font color="green">INFO</font>')
line = line.replace("WARNING", '<font color="orange">WARNING</font>')
line = line.replace("ERROR", '<font color="red">ERROR</font>')
line = line.replace("CRITICAL", '<span style="background-color:red"><font color="white"b>\
CRITICAL</font></span>')
line = line.replace("DEBUG", '<font color="blue">DEBUG</font>')
line = line + "
"
return line
if __name__ == "__main__":
app = QApplication([])
widget = Reader()
# widget.ui.show()
sys.exit(app.exec_())
Log vzniká pomocí modulu logging :
import logging
...
...
logging.basicConfig(
filename=logFilename,
format="%(asctime)s [%(levelname)s] %(module)s: %(lineno)d\
%(funcName)s: %(message)s",
level=logging.DEBUG,
datefmt='%d %H:%M:%S',
filemode="w"
)
Tiskni
Sdílej:
Jako bych slyšel ironii ... ale máš pravdu ...
less --follow-name
tail -f
) program
https://klogg.filimonov.dev anebo
https://glogg.bonnefon.org/index.html
Programy tail, more a všechny ostatní metody nesplňovaly moje požadavky ( nebo neumím číst man a google ).Nebýval kdysi tohle portál pro fanoušky linuxu?
import os import time class TailFIterator: """ Text file iterator, which yields new lines added to the file, like tail -F. It can detect when the file descriptor was changed (logrotated) or the file was truncated (also used by logrotate). You can overload: .on_file_not_found() To change behaviour when the file was followed, but was deleted in the process (logrotated). Standard behaviour is to wait 5 seconds, try again forever. See also .file_not_found_counter for details. .on_no_changes_detected() To decide what to do when no change was detected. Default is to wait 1s. """ def __init__(self, file_path: str, file_mode: str = "rt"): self.file_size = 0 self.file_path = file_path self.file_mode = file_mode self.inode_number = os.stat(file_path).st_ino self.logfile = open(file_path, self.file_mode) self.file_not_found_counter = 0 def __iter__(self): while True: try: size = self._get_current_size() self.file_not_found_counter = 0 except FileNotFoundError as e: self.file_not_found_counter += 1 self.on_file_not_found(self.file_not_found_counter, e) continue if size > self.file_size: self.logfile.seek(self.file_size) for line in self.logfile: yield line self.file_size = self.logfile.tell() # in case the .truncate() was called elif size < self.file_size: self._check_and_handle_logrotate() self.file_size = 0 continue if self._check_and_handle_logrotate(): continue self.on_no_changes_detected() def _get_current_size(self) -> int: return os.stat(self.file_path).st_size def _check_and_handle_logrotate(self) -> bool: current_file_info = os.stat(self.file_path) current_inode_number = current_file_info.st_ino if current_inode_number != self.inode_number: self.inode_number = current_file_info.st_ino self.logfile = open(self.file_path, self.file_mode) self.file_size = 0 return True def on_file_not_found(self, file_not_found_counter: int, exception): if file_not_found_counter > 5: raise exception time.sleep(5) def on_no_changes_detected(self): time.sleep(1)(Psal jsem kdysi pro jeden starší projekt co běžel někde kam jsem nechtěl tahat závislosti).
Děkuji za fakt šikovné podněty ... I komentátorům vašeho příspěvku... Zvlášť Jenda musel prohrabávat staré (.. co - prastaré) archivy, aby našel prastarý kód ( i když podle syntaxe možná zase tak prastarý není, ale stejně) ... fakt dík :)Je to několik let staré, prohledávat jsem nemusel, mám v notionu složku se snippety kam si házím použitelné věci a různé ukázky.
\b(ERROR|INFO|WARN)\b
Výhoda je, že to nebude matchovat třeba information nebo terror.
Escape HTML - například <1> by se měla změnit na <1> , jinak to může být hezký námět nat code injection