Hallo, ich würde gerne, ein subprocess Popen ein Prozeß aufrufen und mich benachrichtigen lassen, wenn dieser fertig ist. Da habe ich auch einen Tipp gefunden: http://stackoverflow.com/questions/2581817/python-subprocess-callback-when-c... exits mit modifizierten Namen schaut das so aus: def popen_callback(on_exit, popen_args): def threaded_run(on_exit, popen_args): print popen_args proc = subprocess.Popen(*popen_args) proc.wait() on_exit() return thread = threading.Thread(target=threaded_run, args=(on_exit, popen_args)) thread.start() return thread Nur habe ich leider Probleme das aufzurufen: In [29]: common.popen_callback(cb, ["sleep", "10"]) ['sleep', '10'] Out[29]: <Thread(Thread-12, started 140538833995520)> Exception in thread Thread-12: Traceback (most recent call last): File "/usr/lib/python2.7/threading.py", line 552, in __bootstrap_inner self.run() File "/usr/lib/python2.7/threading.py", line 505, in run self.__target(*self.__args, **self.__kwargs) File "common.py", line 21, in threaded_run proc = subprocess.Popen(*popen_args) File "/usr/lib/python2.7/subprocess.py", line 629, in __init__ raise TypeError("bufsize must be an integer") TypeError: bufsize must be an integer cb ist meine callback funktion. Ich nehme mal an, er interpretiert die "10" als das zweite Argument für Popen. Eine Reihe von anderen Methoden führte leider auch nicht zum Erfolg. Auch auf die Gefahr hin, mich hier lächerlich zu machen: Wie rufe ich das auf? ;-) Danke! Florian
Er sagt bufsize must be integer dh: Du musst einen Integer anstelle eines Strings übergeben (=keine Anführungszeichen!) common.popen_callback(cb, ["sleep", 10]) -----------------------------------^ -----Original Message----- From: Florian Lindner <mailinglists@xgm.de> Reply-to: Die Deutsche Python Mailingliste <python-de@python.org> To: python-de@python.org Subject: [Python-de] subprocess mit callback Date: Mon, 20 Jun 2011 20:46:14 +0200 Hallo, ich würde gerne, ein subprocess Popen ein Prozeß aufrufen und mich benachrichtigen lassen, wenn dieser fertig ist. Da habe ich auch einen Tipp gefunden: http://stackoverflow.com/questions/2581817/python-subprocess-callback-when-c... exits mit modifizierten Namen schaut das so aus: def popen_callback(on_exit, popen_args): def threaded_run(on_exit, popen_args): print popen_args proc = subprocess.Popen(*popen_args) proc.wait() on_exit() return thread = threading.Thread(target=threaded_run, args=(on_exit, popen_args)) thread.start() return thread Nur habe ich leider Probleme das aufzurufen: In [29]: common.popen_callback(cb, ["sleep", "10"]) ['sleep', '10'] Out[29]: <Thread(Thread-12, started 140538833995520)> Exception in thread Thread-12: Traceback (most recent call last): File "/usr/lib/python2.7/threading.py", line 552, in __bootstrap_inner self.run() File "/usr/lib/python2.7/threading.py", line 505, in run self.__target(*self.__args, **self.__kwargs) File "common.py", line 21, in threaded_run proc = subprocess.Popen(*popen_args) File "/usr/lib/python2.7/subprocess.py", line 629, in __init__ raise TypeError("bufsize must be an integer") TypeError: bufsize must be an integer cb ist meine callback funktion. Ich nehme mal an, er interpretiert die "10" als das zweite Argument für Popen. Eine Reihe von anderen Methoden führte leider auch nicht zum Erfolg. Auch auf die Gefahr hin, mich hier lächerlich zu machen: Wie rufe ich das auf? ;-) Danke! Florian _______________________________________________ python-de maillist - python-de@python.org http://mail.python.org/mailman/listinfo/python-de
Am Montag 20 Juni 2011, 21:17:22 schrieb Alexander Schlarb:
Er sagt bufsize must be integer dh: Du musst einen Integer anstelle eines Strings übergeben (=keine Anführungszeichen!)
common.popen_callback(cb, ["sleep", 10])
Sorry, habe mich da ungenau ausgedrückt. Das auszuführende Kommando soll "sleep 10" (idR /usr/bin/sleep) sein. Popen erwartet in args ja eine Liste mit dem Executable und den Parametern (ausg. shell=True). Mein Problem ist gerade, dass die "10" in buffsize landet und nicht Teil der Liste für args bleibt. Grüße, Florian
-----------------------------------^
-----Original Message----- From: Florian Lindner <mailinglists@xgm.de> Reply-to: Die Deutsche Python Mailingliste <python-de@python.org> To: python-de@python.org Subject: [Python-de] subprocess mit callback Date: Mon, 20 Jun 2011 20:46:14 +0200
Hallo,
ich würde gerne, ein subprocess Popen ein Prozeß aufrufen und mich benachrichtigen lassen, wenn dieser fertig ist. Da habe ich auch einen Tipp gefunden:
http://stackoverflow.com/questions/2581817/python-subprocess-callback-when- cmd- exits
mit modifizierten Namen schaut das so aus:
def popen_callback(on_exit, popen_args): def threaded_run(on_exit, popen_args): print popen_args proc = subprocess.Popen(*popen_args) proc.wait() on_exit() return thread = threading.Thread(target=threaded_run, args=(on_exit, popen_args)) thread.start() return thread
Nur habe ich leider Probleme das aufzurufen:
In [29]: common.popen_callback(cb, ["sleep", "10"]) ['sleep', '10'] Out[29]: <Thread(Thread-12, started 140538833995520)> Exception in thread Thread-12: Traceback (most recent call last): File "/usr/lib/python2.7/threading.py", line 552, in __bootstrap_inner self.run() File "/usr/lib/python2.7/threading.py", line 505, in run self.__target(*self.__args, **self.__kwargs) File "common.py", line 21, in threaded_run proc = subprocess.Popen(*popen_args) File "/usr/lib/python2.7/subprocess.py", line 629, in __init__ raise TypeError("bufsize must be an integer") TypeError: bufsize must be an integer
cb ist meine callback funktion.
Ich nehme mal an, er interpretiert die "10" als das zweite Argument für Popen. Eine Reihe von anderen Methoden führte leider auch nicht zum Erfolg. Auch auf die Gefahr hin, mich hier lächerlich zu machen: Wie rufe ich das auf?
;-)
Danke!
Florian _______________________________________________ python-de maillist - python-de@python.org http://mail.python.org/mailman/listinfo/python-de
Am Montag 20 Juni 2011, 22:18:23 schrieb Florian Lindner:
Am Montag 20 Juni 2011, 21:17:22 schrieb Alexander Schlarb:
Er sagt bufsize must be integer dh: Du musst einen Integer anstelle eines Strings übergeben (=keine Anführungszeichen!)
common.popen_callback(cb, ["sleep", 10])
Sorry, habe mich da ungenau ausgedrückt. Das auszuführende Kommando soll "sleep 10" (idR /usr/bin/sleep) sein. Popen erwartet in args ja eine Liste mit dem Executable und den Parametern (ausg. shell=True). Mein Problem ist gerade, dass die "10" in buffsize landet und nicht Teil der Liste für args bleibt.
Ok, die Lösung kam mit dem drücken des Sende-Knopfes: popen_callback(cb, [["sleep", "10"]]) So, funktioniert es.
Grüße,
Florian
-----------------------------------^
-----Original Message----- From: Florian Lindner <mailinglists@xgm.de> Reply-to: Die Deutsche Python Mailingliste <python-de@python.org> To: python-de@python.org Subject: [Python-de] subprocess mit callback Date: Mon, 20 Jun 2011 20:46:14 +0200
Hallo,
ich würde gerne, ein subprocess Popen ein Prozeß aufrufen und mich benachrichtigen lassen, wenn dieser fertig ist. Da habe ich auch einen Tipp gefunden:
http://stackoverflow.com/questions/2581817/python-subprocess-callback-whe n- cmd- exits
mit modifizierten Namen schaut das so aus:
def popen_callback(on_exit, popen_args): def threaded_run(on_exit, popen_args): print popen_args proc = subprocess.Popen(*popen_args) proc.wait() on_exit() return
thread = threading.Thread(target=threaded_run, args=(on_exit,
popen_args)) thread.start()
return thread
Nur habe ich leider Probleme das aufzurufen:
In [29]: common.popen_callback(cb, ["sleep", "10"]) ['sleep', '10'] Out[29]: <Thread(Thread-12, started 140538833995520)> Exception in thread Thread-12:
Traceback (most recent call last): File "/usr/lib/python2.7/threading.py", line 552, in __bootstrap_inner
self.run()
File "/usr/lib/python2.7/threading.py", line 505, in run
self.__target(*self.__args, **self.__kwargs)
File "common.py", line 21, in threaded_run
proc = subprocess.Popen(*popen_args)
File "/usr/lib/python2.7/subprocess.py", line 629, in __init__
raise TypeError("bufsize must be an integer")
TypeError: bufsize must be an integer
cb ist meine callback funktion.
Ich nehme mal an, er interpretiert die "10" als das zweite Argument für Popen. Eine Reihe von anderen Methoden führte leider auch nicht zum Erfolg. Auch auf die Gefahr hin, mich hier lächerlich zu machen: Wie rufe ich das auf?
;-)
Danke!
Florian _______________________________________________ python-de maillist - python-de@python.org http://mail.python.org/mailman/listinfo/python-de
_______________________________________________ python-de maillist - python-de@python.org http://mail.python.org/mailman/listinfo/python-de
Du könntest auch einfach bei dem Funktionsparameter popen_args ein Sternchen davor machen: def popen_callback(on_exit, *popen_args): ----------------------------^ Python interpretiert das dann als wirf den ganzen Rest bitte in diese Liste. Noch besser wäre es wenn du dahinter dann noch **popen_kwargs setzt und an Popen übergibst: def popen_callback(on_exit, *popen_args, **popen_kwargs): def threaded_run(on_exit, popen_args, popen_kwargs): print popen_args proc = subprocess.Popen(*popen_args, **popen_kwargs) proc.wait() on_exit() return thread = threading.Thread(target=threaded_run, args=(on_exit, popen_args, popen_kwargs)) thread.start() return thread Damit kannst du dann auch noch keyword arguments (daher der name kwargs) übergeben wie zum Beispiel: popen_callback(callback, ["sleep", "10"], shell=True) -----Original Message----- From: Florian Lindner <mailinglists@xgm.de> Reply-to: Die Deutsche Python Mailingliste <python-de@python.org> To: python-de@python.org Subject: Re: [Python-de] subprocess mit callback Date: Mon, 20 Jun 2011 22:20:29 +0200 Am Montag 20 Juni 2011, 22:18:23 schrieb Florian Lindner:
Am Montag 20 Juni 2011, 21:17:22 schrieb Alexander Schlarb:
Er sagt bufsize must be integer dh: Du musst einen Integer anstelle eines Strings übergeben (=keine Anführungszeichen!)
common.popen_callback(cb, ["sleep", 10])
Sorry, habe mich da ungenau ausgedrückt. Das auszuführende Kommando soll "sleep 10" (idR /usr/bin/sleep) sein. Popen erwartet in args ja eine Liste mit dem Executable und den Parametern (ausg. shell=True). Mein Problem ist gerade, dass die "10" in buffsize landet und nicht Teil der Liste für args bleibt.
Ok, die Lösung kam mit dem drücken des Sende-Knopfes: popen_callback(cb, [["sleep", "10"]]) So, funktioniert es.
Grüße,
Florian
-----------------------------------^
-----Original Message----- From: Florian Lindner <mailinglists@xgm.de> Reply-to: Die Deutsche Python Mailingliste <python-de@python.org> To: python-de@python.org Subject: [Python-de] subprocess mit callback Date: Mon, 20 Jun 2011 20:46:14 +0200
Hallo,
ich würde gerne, ein subprocess Popen ein Prozeß aufrufen und mich benachrichtigen lassen, wenn dieser fertig ist. Da habe ich auch einen Tipp gefunden:
http://stackoverflow.com/questions/2581817/python-subprocess-callback-whe n- cmd- exits
mit modifizierten Namen schaut das so aus:
def popen_callback(on_exit, popen_args): def threaded_run(on_exit, popen_args): print popen_args proc = subprocess.Popen(*popen_args) proc.wait() on_exit() return
thread = threading.Thread(target=threaded_run, args=(on_exit,
popen_args)) thread.start()
return thread
Nur habe ich leider Probleme das aufzurufen:
In [29]: common.popen_callback(cb, ["sleep", "10"]) ['sleep', '10'] Out[29]: <Thread(Thread-12, started 140538833995520)> Exception in thread Thread-12:
Traceback (most recent call last): File "/usr/lib/python2.7/threading.py", line 552, in __bootstrap_inner
self.run()
File "/usr/lib/python2.7/threading.py", line 505, in run
self.__target(*self.__args, **self.__kwargs)
File "common.py", line 21, in threaded_run
proc = subprocess.Popen(*popen_args)
File "/usr/lib/python2.7/subprocess.py", line 629, in __init__
raise TypeError("bufsize must be an integer")
TypeError: bufsize must be an integer
cb ist meine callback funktion.
Ich nehme mal an, er interpretiert die "10" als das zweite Argument für Popen. Eine Reihe von anderen Methoden führte leider auch nicht zum Erfolg. Auch auf die Gefahr hin, mich hier lächerlich zu machen: Wie rufe ich das auf?
;-)
Danke!
Florian _______________________________________________ python-de maillist - python-de@python.org http://mail.python.org/mailman/listinfo/python-de
_______________________________________________ python-de maillist - python-de@python.org http://mail.python.org/mailman/listinfo/python-de
_______________________________________________ python-de maillist - python-de@python.org http://mail.python.org/mailman/listinfo/python-de
Am Dienstag 21 Juni 2011, 04:40:41 schrieb Alexander Schlarb:
Du könntest auch einfach bei dem Funktionsparameter popen_args ein Sternchen davor machen:
def popen_callback(on_exit, *popen_args): ----------------------------^
Python interpretiert das dann als wirf den ganzen Rest bitte in diese Liste.
Noch besser wäre es wenn du dahinter dann noch **popen_kwargs setzt und an Popen übergibst:
Wunderbar, danke! Habe es jetzt so umgesetzt. Siehst Du eigentlich eine Möglichkeit, wie man den Code so formulieren kann, dass ich anstelle des Thread() Objektes ein Popen() Objekt zurückgeben kann? Danke, Florian
def popen_callback(on_exit, *popen_args, **popen_kwargs): def threaded_run(on_exit, popen_args, popen_kwargs): print popen_args proc = subprocess.Popen(*popen_args, **popen_kwargs) proc.wait() on_exit() return
thread = threading.Thread(target=threaded_run, args=(on_exit, popen_args, popen_kwargs)) thread.start()
return thread
Damit kannst du dann auch noch keyword arguments (daher der name kwargs) übergeben wie zum Beispiel: popen_callback(callback, ["sleep", "10"], shell=True)
-----Original Message----- From: Florian Lindner <mailinglists@xgm.de> Reply-to: Die Deutsche Python Mailingliste <python-de@python.org> To: python-de@python.org Subject: Re: [Python-de] subprocess mit callback Date: Mon, 20 Jun 2011 22:20:29 +0200
Am Montag 20 Juni 2011, 22:18:23 schrieb Florian Lindner:
Am Montag 20 Juni 2011, 21:17:22 schrieb Alexander Schlarb:
Er sagt bufsize must be integer dh: Du musst einen Integer anstelle eines Strings übergeben (=keine Anführungszeichen!)
common.popen_callback(cb, ["sleep", 10])
Sorry, habe mich da ungenau ausgedrückt. Das auszuführende Kommando soll "sleep 10" (idR /usr/bin/sleep) sein. Popen erwartet in args ja eine Liste mit dem Executable und den Parametern (ausg. shell=True). Mein Problem ist gerade, dass die "10" in buffsize landet und nicht Teil der Liste für args bleibt.
Ok, die Lösung kam mit dem drücken des Sende-Knopfes:
popen_callback(cb, [["sleep", "10"]])
So, funktioniert es.
Grüße,
Florian
-----------------------------------^
-----Original Message----- From: Florian Lindner <mailinglists@xgm.de> Reply-to: Die Deutsche Python Mailingliste <python-de@python.org> To: python-de@python.org Subject: [Python-de] subprocess mit callback Date: Mon, 20 Jun 2011 20:46:14 +0200
Hallo,
ich würde gerne, ein subprocess Popen ein Prozeß aufrufen und mich benachrichtigen lassen, wenn dieser fertig ist. Da habe ich auch einen Tipp gefunden:
http://stackoverflow.com/questions/2581817/python-subprocess-callback-w he n- cmd- exits
mit modifizierten Namen schaut das so aus:
def popen_callback(on_exit, popen_args): def threaded_run(on_exit, popen_args): print popen_args proc = subprocess.Popen(*popen_args) proc.wait() on_exit() return
thread = threading.Thread(target=threaded_run, args=(on_exit,
popen_args)) thread.start()
return thread
Nur habe ich leider Probleme das aufzurufen:
In [29]: common.popen_callback(cb, ["sleep", "10"]) ['sleep', '10'] Out[29]: <Thread(Thread-12, started 140538833995520)> Exception in thread Thread-12:
Traceback (most recent call last): File "/usr/lib/python2.7/threading.py", line 552, in __bootstrap_inner
self.run()
File "/usr/lib/python2.7/threading.py", line 505, in run
self.__target(*self.__args, **self.__kwargs)
File "common.py", line 21, in threaded_run
proc = subprocess.Popen(*popen_args)
File "/usr/lib/python2.7/subprocess.py", line 629, in __init__
raise TypeError("bufsize must be an integer")
TypeError: bufsize must be an integer
cb ist meine callback funktion.
Ich nehme mal an, er interpretiert die "10" als das zweite Argument für Popen. Eine Reihe von anderen Methoden führte leider auch nicht zum Erfolg. Auch auf die Gefahr hin, mich hier lächerlich zu machen: Wie rufe ich das auf?
;-)
Danke!
Florian _______________________________________________ python-de maillist - python-de@python.org http://mail.python.org/mailman/listinfo/python-de
_______________________________________________ python-de maillist - python-de@python.org http://mail.python.org/mailman/listinfo/python-de
_______________________________________________ python-de maillist - python-de@python.org http://mail.python.org/mailman/listinfo/python-de
On Tuesday 28 June 2011, 16:25:04 Florian Lindner wrote:
Am Dienstag 21 Juni 2011, 04:40:41 schrieb Alexander Schlarb:
Du könntest auch einfach bei dem Funktionsparameter popen_args ein Sternchen davor machen:
def popen_callback(on_exit, *popen_args): ----------------------------^
Python interpretiert das dann als wirf den ganzen Rest bitte in diese Liste.
Noch besser wäre es wenn du dahinter dann noch **popen_kwargs setzt und an Popen übergibst:
Wunderbar, danke! Habe es jetzt so umgesetzt. Siehst Du eigentlich eine Möglichkeit, wie man den Code so formulieren kann, dass ich anstelle des Thread() Objektes ein Popen() Objekt zurückgeben kann?
Hmm, ich habe hier eine Lösung, von der ich nicht genau weiss, ob sie zu Deinem Problem passt, aber mal reinschauen kostet ja nichts (ausser ein paar Kalorien ;): http://micheles.googlecode.com/hg/decorator/documentation.html#async Pete
Am Dienstag 28 Juni 2011, 21:10:46 schrieb Hans-Peter Jansen:
On Tuesday 28 June 2011, 16:25:04 Florian Lindner wrote:
Am Dienstag 21 Juni 2011, 04:40:41 schrieb Alexander Schlarb:
Du könntest auch einfach bei dem Funktionsparameter popen_args ein Sternchen davor machen:
def popen_callback(on_exit, *popen_args): ----------------------------^
Python interpretiert das dann als wirf den ganzen Rest bitte in diese Liste.
Noch besser wäre es wenn du dahinter dann noch **popen_kwargs setzt
und an Popen übergibst: Wunderbar, danke! Habe es jetzt so umgesetzt. Siehst Du eigentlich eine Möglichkeit, wie man den Code so formulieren kann, dass ich anstelle des Thread() Objektes ein Popen() Objekt zurückgeben kann?
Hmm, ich habe hier eine Lösung, von der ich nicht genau weiss, ob sie zu Deinem Problem passt, aber mal reinschauen kostet ja nichts (ausser ein paar Kalorien ;):
http://micheles.googlecode.com/hg/decorator/documentation.html#async
Das Modul mit den async decorator schaut schon sehr attraktiv aus. Allerdings habe ich noch ein Problem bei der Benutzung: async = Async(threading.Thread) In [7]: @async ...: def add(b): ...: return b+2 ...: In [8]: add(4) Out[8]: <Thread(add-1, stopped 139819357185792)> Das klappt soweit alles ganz gut. Wenn ich allerdings die callback funktionen benutzen will, bekomme ich es nicht hin: In [9]: def os(result): ...: print "Success", result In [13]: @async(on_success=os) ....: def add(b): ....: return b+2 ....: --------------------------------------------------------------------------- TypeError Traceback (most recent call last) /home/florian/SA/src/<ipython console> in <module>() TypeError: __call__() takes at least 2 arguments (2 given) Einige andere Aufrufkonventionen haben bei mir ebenfalls nicht zum Erfolg geführt. Siehst Du, wie es richtig geht? Danke & Grüße, Florian
Hallo Florian, On 2011-07-02 12:25, Florian Lindner wrote:
Am Dienstag 28 Juni 2011, 21:10:46 schrieb Hans-Peter Jansen:
On Tuesday 28 June 2011, 16:25:04 Florian Lindner wrote: async = Async(threading.Thread)
In [7]: @async ...: def add(b): ...: return b+2 ...:
In [8]: add(4) Out[8]: <Thread(add-1, stopped 139819357185792)>
Das klappt soweit alles ganz gut. Wenn ich allerdings die callback funktionen benutzen will, bekomme ich es nicht hin:
In [9]: def os(result): ...: print "Success", result
ich würde eher davon abraten, eine Funktion so zu nennen wie ein häufig benutztes Modul aus der Standard-Bibliothek. Das kann leicht zu Verwirrung führen.
In [13]: @async(on_success=os) ....: def add(b): ....: return b+2 ....: --------------------------------------------------------------------------- TypeError Traceback (most recent call last)
/home/florian/SA/src/<ipython console> in <module>()
TypeError: __call__() takes at least 2 arguments (2 given)
Die Methode akzeptiert mindestens zwei Parameter, die du auch angegeben hast, aber du bekommst einen TypeError dazu? Hast du die Fehlermeldung richtig übernommen? Viele Grüße Stefan
Am Samstag 02 Juli 2011, 17:35:00 schrieb Stefan Schwarzer:
Hallo Florian,
On 2011-07-02 12:25, Florian Lindner wrote:
Am Dienstag 28 Juni 2011, 21:10:46 schrieb Hans-Peter Jansen:
On Tuesday 28 June 2011, 16:25:04 Florian Lindner wrote: async = Async(threading.Thread)
In [7]: @async
...: def add(b): ...: return b+2
...: In [8]: add(4) Out[8]: <Thread(add-1, stopped 139819357185792)>
Das klappt soweit alles ganz gut. Wenn ich allerdings die callback funktionen benutzen will, bekomme ich es nicht hin:
In [9]: def os(result): ...: print "Success", result
ich würde eher davon abraten, eine Funktion so zu nennen wie ein häufig benutztes Modul aus der Standard-Bibliothek. Das kann leicht zu Verwirrung führen.
Klaro, das war so nur in die Shell gehackt.
TypeError: __call__() takes at least 2 arguments (2 given)
Die Methode akzeptiert mindestens zwei Parameter, die du auch angegeben hast, aber du bekommst einen TypeError dazu? Hast du die Fehlermeldung richtig übernommen?
Ein komplettes Skript schaut jetzt so aus: from common import Async import threading async = Async(threading.Thread) def o_s(result): print "Success: ", result @async(on_success=o_s) def add(x): return x+2 res = add(2) print res und wenn es ausgeführt wird: florian@horus ~/SA/src (git)-[master] % python2 test.py Traceback (most recent call last): File "test.py", line 9, in <module> @async(on_success=o_s) TypeError: __call__() takes at least 2 arguments (2 given) Version von python ist 2.7.2. Wenn ich den Dekorator ohne Argumente benutze funktioniert es, aber halt kein Callback. Viele Grüße, Florian
Florian Lindner wrote:
Am Samstag 02 Juli 2011, 17:35:00 schrieb Stefan Schwarzer:
Hallo Florian,
On 2011-07-02 12:25, Florian Lindner wrote:
Am Dienstag 28 Juni 2011, 21:10:46 schrieb Hans-Peter Jansen:
On Tuesday 28 June 2011, 16:25:04 Florian Lindner wrote: async = Async(threading.Thread)
In [7]: @async
...: def add(b): ...: return b+2
...: In [8]: add(4) Out[8]: <Thread(add-1, stopped 139819357185792)>
Das klappt soweit alles ganz gut. Wenn ich allerdings die callback funktionen benutzen will, bekomme ich es nicht hin:
In [9]: def os(result): ...: print "Success", result
ich würde eher davon abraten, eine Funktion so zu nennen wie ein häufig benutztes Modul aus der Standard-Bibliothek. Das kann leicht zu Verwirrung führen.
Klaro, das war so nur in die Shell gehackt.
TypeError: __call__() takes at least 2 arguments (2 given)
Die Methode akzeptiert mindestens zwei Parameter, die du auch angegeben hast, aber du bekommst einen TypeError dazu? Hast du die Fehlermeldung richtig übernommen?
Ein komplettes Skript schaut jetzt so aus:
from common import Async import threading
async = Async(threading.Thread)
def o_s(result): print "Success: ", result
@async(on_success=o_s) def add(x): return x+2
res = add(2) print res
und wenn es ausgeführt wird:
florian@horus ~/SA/src (git)-[master] % python2 test.py Traceback (most recent call last): File "test.py", line 9, in <module> @async(on_success=o_s) TypeError: __call__() takes at least 2 arguments (2 given)
Version von python ist 2.7.2.
Faszinierende Fehlermeldung; Python 2.6 ist dagegen richtig langweilig:
$ python async.py Traceback (most recent call last): File "async.py", line 68, in <module> @async(on_success=on_success) TypeError: __call__() takes at least 2 non-keyword arguments (1 given)
Wenn ich den Dekorator ohne Argumente benutze funktioniert es, aber halt kein Callback.
Probier es mal zu Fuß: def add(x): return x + 2 add = async(add, on_success=o_s)
Am Montag 04 Juli 2011, 13:57:09 schrieb Peter Otten:
Florian Lindner wrote:
Am Samstag 02 Juli 2011, 17:35:00 schrieb Stefan Schwarzer:
Hallo Florian,
On 2011-07-02 12:25, Florian Lindner wrote:
Am Dienstag 28 Juni 2011, 21:10:46 schrieb Hans-Peter Jansen:
On Tuesday 28 June 2011, 16:25:04 Florian Lindner wrote: async = Async(threading.Thread)
In [7]: @async
...: def add(b): ...: return b+2
...: In [8]: add(4) Out[8]: <Thread(add-1, stopped 139819357185792)>
Das klappt soweit alles ganz gut. Wenn ich allerdings die callback funktionen benutzen will, bekomme ich es nicht hin:
In [9]: def os(result): ...: print "Success", result
ich würde eher davon abraten, eine Funktion so zu nennen wie ein häufig benutztes Modul aus der Standard-Bibliothek. Das kann leicht zu Verwirrung führen.
Klaro, das war so nur in die Shell gehackt.
TypeError: __call__() takes at least 2 arguments (2 given)
Die Methode akzeptiert mindestens zwei Parameter, die du auch angegeben hast, aber du bekommst einen TypeError dazu? Hast du die Fehlermeldung richtig übernommen?
Ein komplettes Skript schaut jetzt so aus:
from common import Async import threading
async = Async(threading.Thread)
def o_s(result): print "Success: ", result
@async(on_success=o_s)
def add(x): return x+2
res = add(2) print res
und wenn es ausgeführt wird:
florian@horus ~/SA/src (git)-[master] % python2 test.py
Traceback (most recent call last): File "test.py", line 9, in <module>
@async(on_success=o_s)
TypeError: __call__() takes at least 2 arguments (2 given)
Version von python ist 2.7.2.
Faszinierende Fehlermeldung; Python 2.6 ist dagegen richtig langweilig:
$ python async.py
Traceback (most recent call last): File "async.py", line 68, in <module> @async(on_success=on_success) TypeError: __call__() takes at least 2 non-keyword arguments (1 given)
Wenn ich den Dekorator ohne Argumente benutze funktioniert es, aber halt kein Callback.
Probier es mal zu Fuß:
def add(x): return x + 2 add = async(add, on_success=o_s)
Das funktioniert: florian@horus ~/SA/src (git)-[master] % python2 test.py Success: <Thread(add-1, started 140544079726336)> 4 bei Python 2.6 ebenfalls? Hast Du eine Idee woran es liegen könnte? Grüße, Florian
Florian Lindner wrote:
Am Montag 04 Juli 2011, 13:57:09 schrieb Peter Otten:
Florian Lindner wrote:
Am Samstag 02 Juli 2011, 17:35:00 schrieb Stefan Schwarzer:
Hallo Florian,
On 2011-07-02 12:25, Florian Lindner wrote:
Am Dienstag 28 Juni 2011, 21:10:46 schrieb Hans-Peter Jansen:
On Tuesday 28 June 2011, 16:25:04 Florian Lindner wrote: async = Async(threading.Thread)
In [7]: @async
...: def add(b): ...: return b+2
...: In [8]: add(4) Out[8]: <Thread(add-1, stopped 139819357185792)>
Das klappt soweit alles ganz gut. Wenn ich allerdings die callback funktionen benutzen will, bekomme ich es nicht hin:
In [9]: def os(result): ...: print "Success", result
ich würde eher davon abraten, eine Funktion so zu nennen wie ein häufig benutztes Modul aus der Standard-Bibliothek. Das kann leicht zu Verwirrung führen.
Klaro, das war so nur in die Shell gehackt.
TypeError: __call__() takes at least 2 arguments (2 given)
Die Methode akzeptiert mindestens zwei Parameter, die du auch angegeben hast, aber du bekommst einen TypeError dazu? Hast du die Fehlermeldung richtig übernommen?
Ein komplettes Skript schaut jetzt so aus:
from common import Async import threading
async = Async(threading.Thread)
def o_s(result): print "Success: ", result
@async(on_success=o_s)
def add(x): return x+2
res = add(2) print res
und wenn es ausgeführt wird:
florian@horus ~/SA/src (git)-[master] % python2 test.py
Traceback (most recent call last): File "test.py", line 9, in <module>
@async(on_success=o_s)
TypeError: __call__() takes at least 2 arguments (2 given)
Version von python ist 2.7.2.
Faszinierende Fehlermeldung; Python 2.6 ist dagegen richtig langweilig:
$ python async.py
Traceback (most recent call last): File "async.py", line 68, in <module> @async(on_success=on_success) TypeError: __call__() takes at least 2 non-keyword arguments (1 given)
Wenn ich den Dekorator ohne Argumente benutze funktioniert es, aber halt kein Callback.
Probier es mal zu Fuß:
def add(x): return x + 2 add = async(add, on_success=o_s)
Das funktioniert:
florian@horus ~/SA/src (git)-[master] % python2 test.py Success: <Thread(add-1, started 140544079726336)> 4
bei Python 2.6 ebenfalls? Hast Du eine Idee woran es liegen könnte?
Ja klar. @async(on_success=callback) def add(x): return x + 2 entspricht def add(x): return x + 2 add = async(on_success=callback)(add) Dafür ist Async.__call__() nicht ausgelegt; es erwartet immer die zu dekorierende Funktion als (abgesehen von self) erstes Argument. Hier eine modifizierte Version, bei der die __call__-Methode eine Fallunterscheidung vornimmt: import itertools from decorator import decorator from functools import partial def on_success(result): # default implementation "Called on the result of the function" print "Default", result def on_failure(exc_info): # default implementation "Called if the function fails" pass def on_closing(): # default implementation "Called at the end, both in case of success and failure" pass class Async(object): """ A decorator converting blocking functions into asynchronous functions, by using threads or processes. Examples: async_with_threads = Async(threading.Thread) async_with_processes = Async(multiprocessing.Process) """ def __init__(self, threadfactory): self.threadfactory = threadfactory def __call__(self, func=None, on_success=on_success, on_failure=on_failure, on_closing=on_closing): if func is None: return partial(self, on_success=on_success, on_failure=on_failure, on_closing=on_closing) # every decorated function has its own independent thread counter func.counter = itertools.count(1) func.on_success = on_success func.on_failure = on_failure func.on_closing = on_closing return decorator(self.call, func) def call(self, func, *args, **kw): def func_wrapper(): try: result = func(*args, **kw) except: func.on_failure(sys.exc_info()) else: return func.on_success(result) finally: func.on_closing() name = '%s-%s' % (func.__name__, func.counter.next()) thread = self.threadfactory(None, func_wrapper, name) thread.start() return thread if __name__ == "__main__": import threading async = Async(threading.Thread) @async def add_one(b): return b+1 add_one(4) def on_success(result): print "Success", result @async(on_success=on_success) def add_two(b): return b+2 add_two(42) Ich habe versucht, so wenig wie möglich an der Klasse zu ändern.
Am Dienstag 05 Juli 2011, 00:35:06 schrieb Peter Otten:
Florian Lindner wrote:
Am Montag 04 Juli 2011, 13:57:09 schrieb Peter Otten:
Florian Lindner wrote:
Am Samstag 02 Juli 2011, 17:35:00 schrieb Stefan Schwarzer:
Hallo Florian,
On 2011-07-02 12:25, Florian Lindner wrote:
Am Dienstag 28 Juni 2011, 21:10:46 schrieb Hans-Peter Jansen: > On Tuesday 28 June 2011, 16:25:04 Florian Lindner wrote: async = Async(threading.Thread)
In [7]: @async
...: def add(b): ...: return b+2
...: In [8]: add(4) Out[8]: <Thread(add-1, stopped 139819357185792)>
Das klappt soweit alles ganz gut. Wenn ich allerdings die callback funktionen benutzen will, bekomme ich es nicht hin:
In [9]: def os(result): ...: print "Success", result
ich würde eher davon abraten, eine Funktion so zu nennen wie ein häufig benutztes Modul aus der Standard-Bibliothek. Das kann leicht zu Verwirrung führen.
Klaro, das war so nur in die Shell gehackt.
TypeError: __call__() takes at least 2 arguments (2 given)
Die Methode akzeptiert mindestens zwei Parameter, die du auch angegeben hast, aber du bekommst einen TypeError dazu? Hast du die Fehlermeldung richtig übernommen?
Ein komplettes Skript schaut jetzt so aus:
from common import Async import threading
async = Async(threading.Thread)
def o_s(result): print "Success: ", result
@async(on_success=o_s)
def add(x): return x+2
res = add(2) print res
und wenn es ausgeführt wird:
florian@horus ~/SA/src (git)-[master] % python2 test.py
Traceback (most recent call last): File "test.py", line 9, in <module>
@async(on_success=o_s)
TypeError: __call__() takes at least 2 arguments (2 given)
Version von python ist 2.7.2.
Faszinierende Fehlermeldung; Python 2.6 ist dagegen richtig langweilig:
$ python async.py
Traceback (most recent call last): File "async.py", line 68, in <module>
@async(on_success=on_success)
TypeError: __call__() takes at least 2 non-keyword arguments (1 given)
Wenn ich den Dekorator ohne Argumente benutze funktioniert es, aber halt kein Callback.
Probier es mal zu Fuß:
def add(x): return x + 2
add = async(add, on_success=o_s)
Das funktioniert:
florian@horus ~/SA/src (git)-[master] % python2 test.py Success: <Thread(add-1, started 140544079726336)>
4
bei Python 2.6 ebenfalls? Hast Du eine Idee woran es liegen könnte?
Ja klar.
@async(on_success=callback) def add(x): return x + 2
entspricht
def add(x): return x + 2 add = async(on_success=callback)(add)
Dafür ist Async.__call__() nicht ausgelegt; es erwartet immer die zu dekorierende Funktion als (abgesehen von self) erstes Argument. Hier eine modifizierte Version, bei der die __call__-Methode eine Fallunterscheidung vornimmt:
[...]
Ich habe versucht, so wenig wie möglich an der Klasse zu ändern.
Super! Vielen Dank, es klappt so! Allerdings hören mein Problemchen mit dem Decorator da nicht auf. ;-) Als ich ihn in meinen eigentlichen Code eingebaut habe: @async(on_sucess = self._cb_run_success) def run(self): pass das Problem ist nun, dass self für den Decorator gar nicht verfügbar ist. Mir fallen da erstmal zwei "Lösungen" ein (in Anführungszeichen, da beide unerprobt) 1) den Callback _cb_run_success zur classmethod machen, damit braucht er kein self mehr. Allerdings greife ich im in der Methode schon auf self zu, müsste meinen Code also irgendwie umbauen. Damit könnte ich die on_success Methode auch gleich komplett außerhalb der Klase stellen. 2) In __init__ der Klasse den Dekorator partial instanziieren (<- richtiger Begriff?) def __init__(self): self.my_async = functools.partial(async(on_success = self.o_s)) Leider - wie ich eben gerade merke - ist damit das Problem nur verschoben. @self.my_async funktioniert leider ebensowenig. Ich habe dazu eine Diskussion gefunden http://stackoverflow.com/questions/3631768/is-it-bad-practice-to-use-self-in... decorators Man kann wohl self im Code des Decorators bekommen, indem man Element [0] der positional Arguments ausliest *args. Das würde die allgemeine Verwendbarkeit des Dekorators wohl leider ziemlich einschränken. Grüße und vielen Dank für alle weiteren Tipps! Florian
Florian Lindner wrote:
Allerdings hören mein Problemchen mit dem Decorator da nicht auf. ;-) Als ich ihn in meinen eigentlichen Code eingebaut habe:
@async(on_sucess = self._cb_run_success) def run(self): pass
das Problem ist nun, dass self für den Decorator gar nicht verfügbar ist.
Mir fallen da erstmal zwei "Lösungen" ein (in Anführungszeichen, da beide unerprobt)
1) den Callback _cb_run_success zur classmethod machen, damit braucht er kein self mehr. Allerdings greife ich im in der Methode schon auf self zu, müsste meinen Code also irgendwie umbauen. Damit könnte ich die on_success Methode auch gleich komplett außerhalb der Klase stellen.
2) In __init__ der Klasse den Dekorator partial instanziieren (<- richtiger Begriff?)
def __init__(self): self.my_async = functools.partial(async(on_success = self.o_s))
Leider - wie ich eben gerade merke - ist damit das Problem nur verschoben. @self.my_async funktioniert leider ebensowenig.
Ich habe dazu eine Diskussion gefunden http://stackoverflow.com/questions/3631768/is-it-bad-practice-to-use-self- in- decorators
Man kann wohl self im Code des Decorators bekommen, indem man Element [0] der positional Arguments ausliest *args. Das würde die allgemeine Verwendbarkeit des Dekorators wohl leider ziemlich einschränken.
Grüße und vielen Dank für alle weiteren Tipps!
Wenn ich dich richtig verstehe, läuft das auf etwas in der Art hinaus: class A(object): def __init__(self, name, offset): self.name = name self.offset = offset self.run = partial(async(self.run, on_success=self.on_success), self) @staticmethod def run(self, x): return self.offset + x def on_success(self, result): print self.name, "-->", result A("foo", 123).run(42) Mir wär das allerdings zu kompliziert.
Am Freitag 08 Juli 2011, 18:10:03 schrieb Peter Otten:
Florian Lindner wrote:
Allerdings hören mein Problemchen mit dem Decorator da nicht auf. ;-) Als
ich ihn in meinen eigentlichen Code eingebaut habe: @async(on_sucess = self._cb_run_success)
def run(self): pass
das Problem ist nun, dass self für den Decorator gar nicht verfügbar ist.
Mir fallen da erstmal zwei "Lösungen" ein (in Anführungszeichen, da beide unerprobt)
1) den Callback _cb_run_success zur classmethod machen, damit braucht er kein self mehr. Allerdings greife ich im in der Methode schon auf self zu, müsste meinen Code also irgendwie umbauen. Damit könnte ich die on_success Methode auch gleich komplett außerhalb der Klase stellen.
2) In __init__ der Klasse den Dekorator partial instanziieren (<- richtiger Begriff?)
def __init__(self): self.my_async = functools.partial(async(on_success = self.o_s))
Leider - wie ich eben gerade merke - ist damit das Problem nur verschoben. @self.my_async funktioniert leider ebensowenig.
Ich habe dazu eine Diskussion gefunden http://stackoverflow.com/questions/3631768/is-it-bad-practice-to-use-sel f-
in-
decorators
Man kann wohl self im Code des Decorators bekommen, indem man Element [0] der positional Arguments ausliest *args. Das würde die allgemeine Verwendbarkeit des Dekorators wohl leider ziemlich einschränken.
Grüße und vielen Dank für alle weiteren Tipps!
Wenn ich dich richtig verstehe, läuft das auf etwas in der Art hinaus:
Ich habe es jetzt hinbekommen, dass es ohne Änderungen am aufrufenden Code funktioniert und gleichzeitig allgemein bleibt: class Async(object): """ A decorator converting blocking functions into asynchronous functions, by using threads or processes. Examples: async_with_threads = Async(threading.Thread) async_with_processes = Async(multiprocessing.Process) """ def __init__(self, threadfactory): self.threadfactory = threadfactory def __call__(self, func=None, on_success=on_success, on_failure=on_failure, on_closing=on_closing): if func is None: return partial(self, on_success=on_success, on_failure=on_failure, on_closing=on_closing) # every decorated function has its own independent thread counter func.counter = itertools.count(1) func.on_success = on_success func.on_failure = on_failure func.on_closing = on_closing return decorator(self.call, func) def call(self, func, *args, **kw): def func_wrapper(): try: result = func(*args, **kw) except: if "self" in getargspec(func.on_failure).args: func.on_failure(args[0], sys.exc_info()) else: func.on_failure(sys.exc_info()) else: if "self" in getargspec(func.on_success).args: return func.on_success(args[0], result) else: return func.on_success(result) finally: if "self" in getargspec(func.on_closing).args: func.on_closing(args[0]) else: func.on_closing() name = '%s-%s' % (func.__name__, func.counter.next()) thread = self.threadfactory(None, func_wrapper, name) thread.start() return thread In call() überprüfe ich die Signaturen der Callback-Funktionen und gebe ggfs. noch das entsprechende self, welches ich aus args[0] bekomme mit. getargspec stammt aus dem Modul inspect. Siehst Du da noch irgendwelche Probleme oder Verbesserungen? Grüße, Florian
Florian Lindner wrote:
def call(self, func, *args, **kw): def func_wrapper(): try: result = func(*args, **kw) except: if "self" in getargspec(func.on_failure).args: func.on_failure(args[0], sys.exc_info()) else: func.on_failure(sys.exc_info()) else: if "self" in getargspec(func.on_success).args: return func.on_success(args[0], result) else: return func.on_success(result) finally: if "self" in getargspec(func.on_closing).args: func.on_closing(args[0]) else: func.on_closing() name = '%s-%s' % (func.__name__, func.counter.next()) thread = self.threadfactory(None, func_wrapper, name) thread.start() return thread
In call() überprüfe ich die Signaturen der Callback-Funktionen und gebe ggfs. noch das entsprechende self, welches ich aus args[0] bekomme mit. getargspec stammt aus dem Modul inspect.
Siehst Du da noch irgendwelche Probleme
Keine Probleme, die in der Praxis auftreten. Einen Trick sauber zwischen Methoden und Funktionen zu unterscheiden gibt's wohl nicht.
oder Verbesserungen?
Vielleicht könntest du den argspec-Voodoo in die __call__()-Methode verlagern.
Am 28.06.2011 16:25, schrieb Florian Lindner:
Siehst Du eigentlich eine Möglichkeit, wie man den Code so formulieren kann, dass ich anstelle des Thread() Objektes ein Popen() Objekt zurückgeben kann?
Ich bin zwar nicht gefragt, antworte aber einfach trotzdem: def popen_callback(on_exit, *popen_args, **popen_kwargs): def threaded_run(on_exit, process): process.wait() on_exit() print popen_args, popen_kwargs proc = subprocess.Popen(*popen_args, **popen_kwargs) thread = threading.Thread(target=threaded_run, args=(on_exit, proc)) thread.start() return proc Anstelle des ganzen Popen-Objektes könnte man auch lediglich die wait()-Methode an threaded_run() übergeben und so aufrufen wie on_exit auch. Damit würde man die Funktion vielleicht etwas allgemeiner halten. -- u1f
Am Mittwoch 29 Juni 2011, 21:40:40 schrieb Ulf Rompe:
Am 28.06.2011 16:25, schrieb Florian Lindner:
Siehst Du eigentlich eine Möglichkeit, wie man den Code so formulieren kann, dass ich anstelle des Thread() Objektes ein Popen() Objekt zurückgeben kann?
Ich bin zwar nicht gefragt, antworte aber einfach trotzdem:
Gut, dass Du Dich auch angesprochen fühlt, ich antworte ja der Liste und weniger den Personen. ;-) Ich habe jetzt zwei Möglichkeiten mein Problem zu lösen. Erstmal kurz zu meinem Problem. Ich schreibe eine Job/Queue-Kontrolle für recht lang laufende Jobs (numerische Berechnungen). Eine Job-Klasse soll über ihren Status (finished, running, waiting, evtl. failed) Auskunft geben. Zu dieser Statusinformation kann ich nun auf zwei Arten gelangen: - Ich nehme das Popen-Objekt und schaue, was mir poll() zurückgibt (Methode nach Ulf) - Ich benutze callbacks und setzte da meinen Status entsprechend. (Methode nach Hans-Peter) Nun frage ich mich natürlich, was die Methoden für Vor- und Nachteile haben. Mit poll() ist meine Klasse an sich erstmal zustandslos, es kann also auch nichts schiefgehen beim Setzen des Zustandes. Mit dem Callbacks wiederum habe ich die Möglichkeit noch Aktionen beim Abschluss des Jobs auszulösen (z.B. Mail verschicken). Was ist Eure Meinung dazu? Es darf - nein soll! - jeder antworten! :-D Grüße, Florian
def popen_callback(on_exit, *popen_args, **popen_kwargs): def threaded_run(on_exit, process): process.wait() on_exit() print popen_args, popen_kwargs proc = subprocess.Popen(*popen_args, **popen_kwargs) thread = threading.Thread(target=threaded_run, args=(on_exit, proc)) thread.start() return proc
Anstelle des ganzen Popen-Objektes könnte man auch lediglich die wait()-Methode an threaded_run() übergeben und so aufrufen wie on_exit auch. Damit würde man die Funktion vielleicht etwas allgemeiner halten.
On Thu, 30 Jun 2011 17:45:04 +0200 Florian Lindner <mailinglists@xgm.de> wrote:
Was ist Eure Meinung dazu?
Das klingt ein wenig wie was Celery so macht: <http://celeryproject.org/>. Hast du dir das mal angesehen? Also, bevor du ggf. das Rad neu erfindest. grüße, Marek
participants (7)
-
Alexander Schlarb
-
Florian Lindner
-
Hans-Peter Jansen
-
Marek Kubica
-
Peter Otten
-
Stefan Schwarzer
-
Ulf Rompe