Na blogu Raspberry Pi byla představena rozšiřující deska Raspberry Pi AI HAT+ 2 s akcelerátorem Hailo-10 a 8 GB RAM. Na rozdíl od předchozí Raspberry Pi AI HAT+ podporuje generativní AI. Cena desky je 130 dolarů.
Wikipedie slaví 25. výročí svého založení. Vznikla 15. ledna 2001 jako doplňkový projekt k dnes již neexistující encyklopedii Nupedia. Doména wikipedia.org byla zaregistrována 12. ledna 2001. Zítra proběhne v Praze Večer svobodné kultury, který pořádá spolek Wikimedia ČR.
Po více než dvou letech od vydání předchozí verze 2.12 byla vydána nová stabilní verze 2.14 systémového zavaděče GNU GRUB (GRand Unified Bootloader, Wikipedie). Přehled novinek v souboru NEWS a v aktualizované dokumentaci.
Google Chrome 144 byl prohlášen za stabilní. Nejnovější stabilní verze 144.0.7559.59 přináší řadu novinek z hlediska uživatelů i vývojářů. Podrobný přehled v poznámkách k vydání. Opraveno bylo 10 bezpečnostních chyb. Vylepšeny byly také nástroje pro vývojáře (YouTube).
Microsoft zveřejnil zdrojový kód XAML Studia a uvolnil ho pod MIT licencí. XAML Studio je nástroj ze světa Windows, určený pro tvorbu uživatelského rozhraní aplikací pomocí XAML (Extensible Application Markup Language). Stalo se tak zhruba po osmi letech od prvního prohlášení Microsoftu, že se tento kód chystá zveřejnit.
TimeCapsule, 'časová kapsle', je jazykový model trénovaný výhradně na datech z určitých míst a časových období, aby se tak napodobila autentická slovní zásoba, způsob vyjadřování a názory dané doby. Na Hugging face jsou k dispozici modely natrénované na historických textech dostupných v oblasti Londýna mezi lety 1800 až 1875.
Radicle byl vydán ve verzi 1.6.0 s kódovým jménem Amaryllis. Jedná se o distribuovanou alternativu k softwarům pro spolupráci jako např. GitLab.
Zemřel Scott Adams, tvůrce komiksových stripů Dilbert parodujících pracovní prostředí velké firmy.
Sdružení CZ.NIC vydalo novou verzi Knot Resolveru (6.1.0). Jedná se o první vydanou stabilní verzi 6, která je nyní oficiálně preferovanou a doporučovanou verzí, namísto předešlé verze 5. Více o Knot Resolveru 6 je možné se dočíst přímo v dokumentaci.
Byl vydán Linux Mint 22.3 s kódovým jménem Zena. Podrobnosti v přehledu novinek a poznámkách k vydání. Vypíchnout lze, že nástroj Systémová hlášení (System Reports) získal mnoho nových funkcí a byl přejmenován na Informace o systému (System Information). Linux Mint 22.3 bude podporován do roku 2029.
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).
. Za starých časů jsem psal něco podobného pro PHP a používalo to externí inotify. Dneska už zbytečné, každý jazyk to podoporuje.
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.
.. jak jsi onehdá snil ... no počkáme ... a snad se dožijem
\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
S těmi newline a načítáním nového souboru - bude tam nějaká komplexita navíc, neboť match či přidání nového řádku by se mělo dít jenom v případech, kdy se dokončilo načtení aspoň jednoho řádku. To jenom detail, když už to tak komplikuju.