Pyro

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
ravenheart
User
Beiträge: 70
Registriert: Mittwoch 10. November 2010, 18:41

Da mir Pyro empfohlen wurde, versuche ich gerade mich da ein wenig einzuarbeiten.

Was mir frühe Probleme bereitet, ist der Nameserver. Ich verstehe nicht, was genau das sein soll und wozu man den brauchen kann.
Ich kann ihn zwar nutzen, allerdings verstehe ich ihn nicht.

Des weiteren habe ich keine Methode gefunden, den Nameserver als Daemon zu starten.

Wenn ihr mir helfen könnt, bitte tut es^^
BlackJack

@ravenheart: Der Nameserver ist dazu da, dass Pyro-Clients den Pyro-Server für ein Objekt nicht direkt kennen müssen, sondern über den Nameserver über einen Namen an die URI vom Server+Objekt kommen können. Server melden ihre Objekte beim Nameserver an und Clients holen sie sich von dort.

Unter Unix sollte es ein `pyro-nsd`-Programm geben um den Server als Daemon zu starten. Wenn Du Pyro über die Paketverwaltung installiert hast, besteht die Chance, dass es ein Kontrollskript unter `/etc/init.d/` dafür gibt. Unter Ubuntu zum Beispiel:

Code: Alles auswählen

bj@s8n:~$ /etc/init.d/pyro-nsd 
Pyro name server daemon: disabled, see /etc/default/pyro-nsd
In der Angegebenen Datei kann man den Daemon-Start aktivieren/konfigurieren.
ravenheart
User
Beiträge: 70
Registriert: Mittwoch 10. November 2010, 18:41

So ganz kapier ich das ganze noch nicht.
Ich kann zwar jetzt auf Klassen remote zugreifen, aber ich weiß nicht wie ich einzelne Instanzen "verschicke"

Also was ich kann, ist eine Klasse in einem Server-Programm anlegen und ein Client-Programm schreiben, welches Instanzen dieser Klasse erstellt.

Was ich aber möchte ist:

csv.sucheZeilen("col1 > 6").subtrahiere("col1", 1).dump("neue_csv")

dass in einer csv Datei Zielen gesucht werden, in denen Spalte 1 einen Wert größer 6 haben und dann dort 1 abzieht und das Ergebnis als neue_csv abspeichert

Bisher ist es so realisiert, dass die Methode sucheZeilen in eine temporäre Textdatei schreibt und alle Zeilen abarbeitet.
Dann wird mit dieser temporären Datei ein neues csv-objekt erzeugt, das dann die Subtraktion ausführt und wiederum in eine temporäre Textdatei schreibt.
Im letzten Schritt wird die temporäre Datei kopiert.

Nun will ich mir das ganze Textdateien schreiben sparen und wünsche mir folgendes:

suche Zeilen ist ein Prozess, der die Zeilen auffindet. Wenn eine Zeile gefunden wurde wird diese an den nächsten Prozess "Subtrahiere" , der wiederum seine Sache mit den einkommenden Zeilen macht. Dann geht es an den Prozess dump, der die Schreibarbeit übernimmt.

Das ganze würde ich jetzt mal mit Pyro in Angriff nehmen wollen, aber ich seh den ANfang nicht. Ich schaffe es nichtmal mit einem Minimalfall.

Kann mir jmd helfen?
deets

Du kannst schon Objekte "verschicken" - aber da gibt's zwei ganz entscheidende Arten:

- Value-Objekte, also strings, zahlen, listen, tupel, dictionaries, und generell alles ,was sich vernuenftig serialisieren laesst.
- Proxy-Objekte. Das sind diejenigen, die Methoden (und wer mag sogar Attribute) exponieren, also letztlich die eigentlichen Server.

Erstere sind deine Daten, in deinem Fall also zB ein Zeilen-Objekt, das vielleicht so aussehen koennte:

Code: Alles auswählen


class Row(object):

   def __init__(self, rowdata, linenumber):
         self.rowdata = rowdata
         self.linenumber = linenumber
Dein erster Client, der CSV-Reader, liest das CSV ein und verpackt die einzelnen Zeilen in ein Row-Objekt. Er holt sich dann eine Referenz auf den Server, bzw. auf ein benamtes Proxy-Objekt darin - koennet zB row_sink heissen. Und das hat eine Methode, "process_row", an die der Client ein Row-Objekt weiterreicht.

Und das war's doch schon. Rinse & Repeat - jeder Server kann ja auch wieder Client sein, fuer einen anderen Server.

Dann gibt's noch die Themen Callbacks & Event-System, aber die sehe ich bei dir erstmal nicht.
ravenheart
User
Beiträge: 70
Registriert: Mittwoch 10. November 2010, 18:41

Kannst du mir noch sagen, wie das Weiterschicken genau funktioniert?
Eine propagate-Methode?

Das ist das, was mir richtig üble Schwierigkeiten bereitet.
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

ravenheart hat geschrieben:Was mir frühe Probleme bereitet, ist der Nameserver. Ich verstehe nicht, was genau das sein soll und wozu man den brauchen kann.
Ich kann ihn zwar nutzen, allerdings verstehe ich ihn nicht.
Er ist dazu da, um eine Ortstransparenz zu gewährleisten.
ravenheart hat geschrieben:Kannst du mir noch sagen, wie das Weiterschicken genau funktioniert?
Eine propagate-Methode?
Bist du noch nicht auf die Examples von Pyro gestoßen? Diese sind eigentlich selbsterklärend.
z.B. hier: http://www.xs4all.nl/~irmen/pyro3/manual/8-example.html
„Lieber von den Richtigen kritisiert als von den Falschen gelobt werden.“
Gerhard Kocher

http://ms4py.org/
ravenheart
User
Beiträge: 70
Registriert: Mittwoch 10. November 2010, 18:41

Das Beispiel habe ich gefunden, und soweit klappt ja auch alles. Nur das "Versenden" von Instanzen ist mir schleierhaft.
In den beiden Beispielen wird eine Klasse aufgerufen.

Würde folgendes irgend wie ausbaubar sinn machen:

Code: Alles auswählen

class MyClass:
  pass

obj = Pyro.core.BaseObj()

csv = MyClass()
daemon.connect(obj.delegateTo(csv))
Auch die Sache, wenn ich keinen Namen angebe, wie ich darauf zurückgreife kommt mir momentan sehr schwierig vor.
deets

Naja, das macht schon Sinn - nur, wofuer genau ist nicht klar.

Hier mal ein gaaanz simples Beispiel:

Code: Alles auswählen

import Pyro.core

class RowCruncher(object):

    def process_row(self, row):
        print 'process_row', row

Pyro.core.initServer()

daemon = Pyro.core.Daemon()
rc_proxy = Pyro.core.ObjBase()
rc_proxy.delegateTo(RowCruncher())
daemon.connect(rc_proxy,'row_cruncher')
daemon.requestLoop()
Und der client dazu sieht so aus:

Code: Alles auswählen

Welcome to rlcompleter2 0.98
for nice experiences hit <tab> multiple times
>>> import Pyro.core
>>> Pyro.core.initClient()
>>> 
>>> obj = Pyro.core.getProxyForURI('PYROLOC://localhost/row_cruncher')
>>> obj.process_row("row")
>>> 
Da mit kommt "row" beim Server an.
ravenheart
User
Beiträge: 70
Registriert: Mittwoch 10. November 2010, 18:41

Hmm danke.

Ich bin für heute zu kaputt, aber ich werde morgen versuchen, das was du mir gegeben hast mal auszubauen. Im Moment sehe ich zwar immer noch nur Fragezeichen. Aber das liegt daran, dass ich bisher weder mit Multiprocessing noch Netzwerk noch viel RMI gemacht hab (von einem kleinen RMI-Projekt abgesehen)
BlackJack

@ravenheart: Also zumindest bei den Beispielen die Du gegeben hast wird das Ganze höchstwahrscheinlich viel komplizierter und langsamer werden, als es ganz einfach mit Iteratoren/Generatoren zu lösen. Ich sehe nicht, dass der ganze Mehraufwand mit den Prozessen und dem Verschicken der Daten über RMI-Mechanismen, durch doch nur sehr bedingt parallele Ausführung aufgewogen wird.

Mach das doch erst einmal mit Iteratoren/Generatoren um die temporären Dateien loszuwerden. Die Lösung kannst Du danach ja immer noch mit Pyro verteilen um die einzelnen Verarbeitungsschritte auf verschiedene Prozesse zu verteilen, falls Du Dir Geschwindigkeitsvorteile davon versprichst. Oder anders herum gesagt: Wenn Du die einzelnen Arbeitsschritte auf verschiedene Prozesse verteilst, musst Du ja sowieso so etwas wie Iteratoren/Generatoren implementieren. Daran kommst Du kaum vorbei. Das ist ja schliesslich das gleiche Konzept wie Pipelines in der Shell und so etwas möchtest Du ja haben.

Irgendwie hatten wir das Thema aber auch schon mal…
Antworten