Seite 1 von 1

[Geklärt]Wie genau impl. man einen file descriptor (fileno)?

Verfasst: Sonntag 28. Januar 2007, 12:52
von sape
Hi.

Code: Alles auswählen

In [10]: file.fileno??
Type:           method_descriptor
Base Class:     <type 'method_descriptor'>
String Form:    <method 'fileno' of 'file' objects>
Namespace:      Python builtin
Docstring [source file open failed]:
    fileno() -> integer "file descriptor".

This is needed for lower-level file interfaces, such os.read().
Es geht um folgendes:

Code: Alles auswählen

process = subprocess.Popen(
            ('python', 'testScript.py'),
            shell = True,
            stdout = subprocess.PIPE,
            stderr = subprocess.PIPE,
            stdin = subprocess.PIPE
        ) 
Wenn an ``stdin`` subprocess.PIPE übergeben wird, dan wird der Output vom ``'testScript.py'`` ungepufert ausgegeben (Also nicht erst wenn der Prozess Terminiert wurde).

subprocess.PIPE ist ein file descriptor, der dem Stream(?) PIPE zugewiesen ist bzw. assoziert wird (wie auch immer).

Code: Alles auswählen

# subprocess.py
PIPE = -1
STDOUT = -2
So nun ist die Frage wie ich so einen eigenen Stream (Pseudo-File) schreiben mit einem file descriptor?

Ein Pseudo-File habe ich schon mal kurz zusammengehackt:

Code: Alles auswählen

[...]
class MainFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, parent=None, title="Test")
        [...]
        # Für die jenigen die sich mit wxPython nicht auskennen:
        # Das ist ein Textfeld in den Texte eingeben werden könne wie mit
        # MS Notepad.
        self.txt_ctrl = wx.TextCtrl(self.panel, style=wx.TE_MULTILINE) 
        [...]

    def OnRunScript(self, event=None):
        import wx.py.pseudo
            class PseudoFileOut(wx.py.pseudo.PseudoFileOut):
                def __init__(self, txt_ctrl_ref):
                    self.txt_ctrl_ref = txt_ctrl_ref
                def write(self, t):
                    # Es wird alles ins ``wx.TextCtrl`` Textfeld geschrieben.
                    print >> self.txt_ctrl_ref, t
        
        pfo = PseudoFileOut(self.txt_ctrl)
        pfo.write("test")
[...]
Das funktioniert auch soweit. Nun muss ich aber die Methode ``fileno`` implementieren, die mir einen file descriptor zurückliefert der aber auch irgendwo "registriert ist" intern (In den tiefen von Python), damit ``subprocess.Popen`` weiß wo er seine Output ausgeben soll :? -- ``subprocess.Popen`` Kann mit ``std*`` was anfangen und auch mit Objekten die mit ``file`` erzeugt wurden sind, da die ``fileno`` implementiert haben...Jetzt muss es irgendwo was magisches geben mit dem ich auch sowas auch machen kann oder?

Leider ist mein Wissen über das File-System beschränkt und weiß daher nicht wie man sowas realisiert.


lg
sape

Verfasst: Sonntag 28. Januar 2007, 13:24
von BlackJack
Die Konstanten bei `subprocess` sind keine Dateideskriptoren, das sind einfach nur Konstanten die der Programmierer vom `subprocess`-Modul so definiert hat.

Und Du kannst keine Dateideskriptoren selber erzeugen, die müssen immer vom Betriebssystem kommen.

Verfasst: Sonntag 28. Januar 2007, 13:44
von sape
BlackJack hat geschrieben:Die Konstanten bei `subprocess` sind keine Dateideskriptoren, das sind einfach nur Konstanten die der Programmierer vom `subprocess`-Modul so definiert hat.
Warum wird den wenn ich einen Pseudo-Stream übergebe ein ``fileno`` erwartet?

Code: Alles auswählen

process = subprocess.Popen(
            ('python -u', 'testScript.py'), 
            shell = True,
            stdout = pfo, 
            #stderr = 100,
        )
AttributeError: PseudoFileOut instance has no attribute 'fileno'
Wenn ich mit ``file`` z.B: eine Datei öffne und den Stream an einen Objekt binde und dann das Objekt an stdout übergebe, wird ``fileno`` aufgerufen, der einen Deskriptor (Ein Intergerwert mit oder ohne Vorzeichen) zurückliefert, der eine Assoziation zum Stream bildet (oder so ähnliche).

Die Konstanten PIPE (-1) ist der Deskriptor für die Pipe der mit der Pipe Assoziiert wird (-1 ist immer eine Assoziation zur Pipe und -2 zu stdout. Das ist Intern schon fest definiert/belegt). -- Es sind also wohl deskriptoren.

So eine Assoziation möchte ich gerne selber machen.
BlackJack hat geschrieben: Und Du kannst keine Dateideskriptoren selber erzeugen, die müssen immer vom Betriebssystem kommen.
Es muss doch möglich sein ein Pseudo-Deskriptor zu erzeugen? Wenn ich eine Datei öffne ist klar das dass das OS regelt. std* ist vorab definiert, genauso wie die Pipe, auch klar. Es wird doch eine Möglcihkeit geben die Mechanismen selber zu nutzen?

lg

Verfasst: Sonntag 28. Januar 2007, 14:12
von BlackJack
sape hat geschrieben:
BlackJack hat geschrieben:Die Konstanten bei `subprocess` sind keine Dateideskriptoren, das sind einfach nur Konstanten die der Programmierer vom `subprocess`-Modul so definiert hat.
Warum wird den wenn ich einen Pseudo-Stream übergebe ein ``fileno`` erwartet?
Weil man die Ausgabe(n) auch auf vorhandene Dateien umlenken können soll.

Code: Alles auswählen

process = subprocess.Popen(
            ('python -u', 'testScript.py'), 
            shell = True,
            stdout = pfo, 
            #stderr = 100,
        )
AttributeError: PseudoFileOut instance has no attribute 'fileno'
Wenn ich mit ``file`` z.B: eine Datei öffne und den Stream an einen Objekt binde und dann das Objekt an stdout übergebe, wird ``fileno`` aufgerufen, der einen Deskriptor (Ein Intergerwert mit oder ohne Vorzeichen) zurückliefert, der eine Assoziation zum Stream bildet (oder so ähnliche).
Bis hierhin richtig, die Deskriptoren kannst Du aber auf kleine positive Zahlen beschränken…
Die Konstanten PIPE (-1) ist der Deskriptor für die Pipe der mit der Pipe Assoziiert wird (-1 ist immer eine Assoziation zur Pipe und -2 zu stdout. Das ist Intern schon fest definiert/belegt). -- Es sind also wohl deskriptoren.
…und das ist falsch. `PIPE` und `STDOUT können schon deshalb keine Deskriptoren sein, weil es diese Dateien zu dem Zeitpunkt noch gar nicht gibt. Die werden erst beim Aufruf des anderen Programms erzeugt und haben dann auch echte Deskriptoren:

Code: Alles auswählen

In [52]: subprocess.PIPE
Out[52]: -1

In [53]: a = subprocess.Popen('ls', stdout=subprocess.PIPE)

In [54]: a.stdout.fileno()
Out[54]: 4
BlackJack hat geschrieben: Und Du kannst keine Dateideskriptoren selber erzeugen, die müssen immer vom Betriebssystem kommen.
Es muss doch möglich sein ein Pseudo-Deskriptor zu erzeugen?
Nein.

Verfasst: Sonntag 28. Januar 2007, 14:20
von sape
BlackJack hat geschrieben: …und das ist falsch. `PIPE` und `STDOUT können schon deshalb keine Deskriptoren sein, weil es diese Dateien zu dem Zeitpunkt noch gar nicht gibt. Die werden erst beim Aufruf des anderen Programms erzeugt und haben dann auch echte Deskriptoren:
[...]
BlackJack hat geschrieben: Und Du kannst keine Dateideskriptoren selber erzeugen, die müssen immer vom Betriebssystem kommen.
Es muss doch möglich sein ein Pseudo-Deskriptor zu erzeugen?[/quote]

Nein.[/quote]
Ah, ok. Wusste ich nicht. Dann müssen es Dateien sein. Hmm, ok ich werde mal ein wenig mit ``mmap`` spielen.

Danke für die Infos.


lg
sape