[Python] Stdout redirecten naar logger

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • CAPSLOCK2000
  • Registratie: Februari 2003
  • Laatst online: 11-09 21:28

CAPSLOCK2000

zie teletekst pagina 888

Topicstarter
Hoe lees ik stdout van een subprocess in, zonder te wachten tot het subproces termineerd?

Ik heb een Python programma dat een ander proces start.
Dat andere proces genereert heel veel output. Met veel bedoel ik 1 terrabyte.
Van die output wil ik de laatste 100 megabyte op schijf bewaren.
Ik kan niet voorspellen wat de laatste 100 mb is, en ik moet dus permanent de laatste 100 mb bij houden, bij voorkeur in handzame files van 10 mb per stuk.

Het hoeft niet precies 100 mb te zijn, 50 of 200 is net zo goed, als ik maar een flink stuk van het einde heb.
Hoe doe ik dat?


Ik had zelf het idee om de Python logging module te gebruiken, die zorgt in ieder geval voor het opslaan in files en het roteren van die files. Dat werkt op zich als een trein, maar ik krijg de output van mijn subprocess er niet in geperst. De subprocess module die ik gebruik wil een pipe of een file object hebben om stdout naar toe te sturen. Ik dacht dat ik het prachtig voor elkaar had, maar het werkt niet.
Tijd voor wat code:

Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class StdWrapper():
        def __init__(self, logger):
                self.logger = logger

        def fileno(self):
                return -1

class StdOutWrapper(StdWrapper):
        def write(self, msg):
                self.logger.INFO(msg)

class StdErrWrapper(StdWrapper):
        def write(self, msg):
                self.logger.ERROR(msg)

logger = logging.getLogger()
subprocess.Popen("echo hoi", stdout=StdOutWrapper(logger), stderr=StdErrWrapper(logger))


Het probleem is dat mijn StdWrapper geen echt file object is.
Specifiek omdat Popen gebruik maakt van de .fileno() functie van file-objects.
Ik zie niet in hoe ik daar om heen kan. Ik kan die functie wel aanmaken, maar daarmee geeft hij nog geen geldige file handle terug.
Iemand een oplossing?


Het alternatief is een pipe gebruiken. Ik denk dat ik dan een tweede thread moet openen die in een loop uit die pipe probeert te lezen. Dat is een oplossing die ik liever niet gebruik, het voelt als te ingewikkeld voor dit simpele probleem, en lezen uit pipes is altijd maar gedoe.

PS. Ik ken Popen.communicate(), het grote probleem dat die wacht tot het subprocess klaar is, en in de tussentijd alles in je geheugen probeert op te slaan, wat in mijn geval geen optie is (tenzij iemand een paar terrabyte ram over heeft). De handleiding waarschuwt er specifiek voor om deze functie niet te gebruiken als je veel output hebt. Wat je dan wel moet doen vermelden ze niet.

PS2. Als het echt niet anders gaat dan maak ik wel een extra proces aan dat stdin naar een logfile weg schrijft en dan pipe ik het daar wel door. Ter leringe ende vermaeke zou ik echter graag een nette Python oplossing zien.

This post is warranted for the full amount you paid me for it.


  • user109731
  • Registratie: Maart 2004
  • Niet online
Werkt iets als dit niet:
Python:
1
2
3
4
process = subprocess.Popen(name, stdout=subprocess.PIPE)

for line in process.stdout:
    logger.info(line)
CAPSLOCK2000 schreef op dinsdag 15 september 2009 @ 23:58:
PS2. Als het echt niet anders gaat dan maak ik wel een extra proces aan dat stdin naar een logfile weg schrijft en dan pipe ik het daar wel door. Ter leringe ende vermaeke zou ik echter graag een nette Python oplossing zien.
Onder *nix en OS X zou je ook simpelweg tail kunnen gebruiken...
$ myprocess | tail --bytes=X

[ Voor 3% gewijzigd door user109731 op 16-09-2009 11:50 ]


  • CAPSLOCK2000
  • Registratie: Februari 2003
  • Laatst online: 11-09 21:28

CAPSLOCK2000

zie teletekst pagina 888

Topicstarter
JanDM schreef op woensdag 16 september 2009 @ 11:44:

Onder *nix en OS X zou je ook simpelweg tail kunnen gebruiken...
$ myprocess | tail --bytes=X
Nee, dat is geen optie. De laatste 100MB _op dat moment_ moet op schijf worden bijgehouden, zodat we de inhoud kunnen bestuderen terwijl het proces verder draait.
Tail zou wachten tot het proces helemaal klaar is, en dan de laatste 100MB pakken.

Het eindresultaat is hetzelfde, maar niet terwijl het draait.

This post is warranted for the full amount you paid me for it.


  • Bryan Tong Minh
  • Registratie: Juli 2008
  • Laatst online: 18-07 12:49
Waarom is het gebruik van pipes (via subprocess.PIPE) een probleem? Je hoeft geen thread te gebruiken om zowel stdout als stderr uit te lezen als je gebruik maakt van de select module.

  • CAPSLOCK2000
  • Registratie: Februari 2003
  • Laatst online: 11-09 21:28

CAPSLOCK2000

zie teletekst pagina 888

Topicstarter
Ik geloof dat dit is waar ik naar op zoek was.
Bedankt.

This post is warranted for the full amount you paid me for it.