Seite 2 von 4

Re: Durchlaufzeit von Funktionen rausfinden / Datum angeben

Verfasst: Freitag 9. Januar 2015, 00:35
von Serpens66
@BlackJack:
ooookay.. ich glaub die hälfte habe ich verstanden ^^

Kannst du mir denn nun für mein Vorhaben sagen, was besser geeignet wäre? Ich möchte einfach gleichzeitig mehrere API anfragen an unterschiedliche Seiten schicken und die Ergebnisse auswerten. Eine API Abfrage dauert so 1-2 sekunden, grob geschätzt, weshalb es halt sinnvoll ist, das gleichzeitig und nicht nacheinander zu machen.

Bzw. brauchst du mir eig nur sagen, ob threading geeignet ist. Das gefällt mir vom Aufbau besser und ich habe es soweit auch gut verstanden und kann es denke ich problemlos auf mein Vorhaben anwenden :)

edit:
weil ich grad dafür keinen extra thread aufmachen möchte:
wie heißt eine Funktion, die so arbeitet wie das hier: http://www.clonk.de/docs/de/sdk/script/fn/BoundBy.html ?
Habe leider keine Ahnung wie man nach sowas suchen soll, da es offensichtlich nicht "boundby" heißt. Habe schon mehrere webseiten über max() und min() abgesucht, ob da auch die gesuchte Funktion erwähnt wird, weil es ja ein ähnliches Verhalten ist...
(zur Not könnte man es auch mit einer if-Verschachltelung lösen)

Re: Durchlaufzeit von Funktionen rausfinden / Datum angeben

Verfasst: Freitag 9. Januar 2015, 01:33
von BlackJack
@Serpens66: Was besser geeignet ist kann man nicht so einfach sagen. Wenn es nicht um CPU-Last geht sondern primär darum die Wartezeiten beim IO zu parallelisieren würde ich keine Prozesse starten. Ob nun etwas selbst geschriebenes mit `threading` oder `concurrent.future` würde ich daran festmachen wie viele Threads gleichzeitig gestartet werden. Wenn das potentiell unbegrenzt ist und man sich selber einen Threadpool implementieren muss würde ich `concurrent.futures` verwenden bevor ich so etwas selber schreibe. Ich würde wahrscheinlich grundsätzlich zu `concurrent.futures` tendieren, solange da nicht etwas gegen spricht.

So ein `bound_by()` kann man sich doch aus `min()` und `max()` ganz simpel basteln. Da braucht man keine ``if``\s für: ``max(lower, min(upper, x))``.

Re: Durchlaufzeit von Funktionen rausfinden / Datum angeben

Verfasst: Freitag 9. Januar 2015, 02:21
von pillmuncher

Re: Durchlaufzeit von Funktionen rausfinden / Datum angeben

Verfasst: Freitag 9. Januar 2015, 02:35
von BlackJack
Beazley ist ja ziemlich Anti-Thread eingestellt. Solange es Vorteile bringt welche zu verwenden würde ich da jetzt nicht so stark darauf Abheben dass es ohne GIL mehr bringen würde. Und selbst wenn es von der Geschwindigkeit her gar nichts bringen sollte, kann es trotzdem praktisch oder sogar notwendig sein unabhängige Ablaufstränge zu programmieren, zum Beispiel bei den meisten GUI-Rahmenwerken wenn etwas im Hintergrund passieren soll.

Re: Durchlaufzeit von Funktionen rausfinden / Datum angeben

Verfasst: Freitag 9. Januar 2015, 07:21
von Sirius3
@Serpens66: Wenn es sowieso nur um die Parallelisierung der Wartezeit auf Web-Services geht, werfe ich einfach mal asynio in den Raum. Das ist genau dafür gemacht, und mit aiohttp scheinen Webabfragen auch nicht viel anders zu sein als mit requests. Der Overhead für die "Thread"-Verwaltung ist damit quasi 0 und man muß sich kaum Gedanken über gemeinsam genutzte Resourcen machen.

Re: Durchlaufzeit von Funktionen rausfinden / Datum angeben

Verfasst: Freitag 9. Januar 2015, 08:36
von lackschuh
@pillmuncher

Wie schaut es mit multiprocessing aus?

- Threads: nein
- Multiprocessing: jein
- Iteration: ja

There are three types of bugs: your bugs, my bugs and threads

Re: Durchlaufzeit von Funktionen rausfinden / Datum angeben

Verfasst: Freitag 9. Januar 2015, 11:12
von pillmuncher
Das hat Beazley in dem verlinkten Vortrag gesagt:
Python and Threads, you know. Threads. Okay. So.. so.. hot button topic, you know, it's like, every new version of Python comes out and people like "Oh, you got rid of the Global Interpreter Lock yet?" - "No." - "Ah, that sucks."

So, threads, you know, you talk to people... "What are they good for?" - "Nothing." And... here's the thing, actually threads in Python are awsome at doing nothing. Like, if you want to sleep or wait for IO or something, threads work great for that. Threads can wait as fast as anything out there.
Das letzte Mal, als ich nachgesehen habe, fiel das Abrufen und Einlesen einer HTML-Seite von einem Server noch unter die Rubrik IO. Da würden Beazley und ich wohl schon Threads verwenden. Oder man verwendet, wie Sirius3 schrieb, asyncio, sofern man Python 3.4 benutzt. Das einfachste wäre aber vielleicht concurrent.futures. Das gibt es schon seit Python 3.2. Das vorliegende Problem wird sogar im Beispiel in der Doku behandelt.

Re: Durchlaufzeit von Funktionen rausfinden / Datum angeben

Verfasst: Freitag 9. Januar 2015, 14:14
von Serpens66
hmm. jetzt verwirrt ihr mich aber =/

"concurrent.futures" hatte ich im vorletzten Post von mir ja ausprobiert und es hat länger als mit threads gedauert. Auch gefällt mir das einstellen von workers nicht, das sieht doch ziemlich Fehler anfällig aus =/ Mit Threads ist die Umsetzung soweit ich das bisher beurteilen kann ziemlich leicht und vorallem verständlich. "concurrent.futures" hab ich noch nicht so wirklich verstanden.

inwiefern ist jetzt asyncio besser für mein Problem geeignet als threads? soweit ich das verstanden habe, muss ich es anstele von requests nehmen? Habe mich stundenlang in requests eingelesen, weshalb ich schon sehr gerne dabei bleiben würde, da es für die API abfragen auch wirklich sehr leicht anzuwenden ist (im vergleich zu diesem "urllib.request, urllib.parse, urllib.error" rumgehobse).

Also was spricht denn nun gegen threads innerhalb meiner Anwendung? Soweit meine Tests mit dem Skript von EyDu es zeigen, funktioniert es zumindest mit der sleep funktion ziemlich gut. Wird es das mit API abfragen nicht mehr tun?

Ist es also nun eine "Glaubensfrage" hier, wo der praktische Nutzen der 3 Möglichkeiten für Anfänger vernachlässigbar ist, oder wäre es schon wichtig, sich auch als Anfänger damit zu beschäftigen? (gibt ja viele solche feinen unterschiede, die man schon kennen sollte,aber einen Anfänger doch stark überfordern und es für diesen dann eig erstmal noch egal ist)

Re: Durchlaufzeit von Funktionen rausfinden / Datum angeben

Verfasst: Freitag 9. Januar 2015, 14:37
von pillmuncher
@Serpens66: Threads funktionieren wunderbar, wenn die Aufgabe IO bound ist. concurrent.futures verwendet wahlweise Prozesse oder Threads. In deinem Code hast du Prozesse verwendet. Versuch es mal mit concurrent.futures.ThreadPoolExecutor, wie in dem Beispiel, das ich in meinem letzten Post verlinkt habe, und schau, ob es damit schnell genug ist.

Grundsätzlich zum Thema Futures: die Idee dabei ist, dass man eine Aktion, die parallel ausgeführt werden soll und anschließend ein Ergebnis zurückliefert, nach folgendem Muster laufen lässt (Pseudocode):

Code: Alles auswählen

future = Future(action)       # <-- startet action in einem anderen Thread/Prozess
do some stuff
result = future.get_result()  # <-- falls action fertig ist, bekommt man das Ergebnis sofort, 
                              #     falls nicht, wird gewartet, bis action fertig ist.
Dabei kann man natürlich mehrere Futures parallel laufen lassen, zB. mit ThreadPoolExecutor.map(). Darüber kann man dann iterieren und bekommt die Ergebnisse in der Reihenfolge, wie sie fertigestellt wurden.

Re: Durchlaufzeit von Funktionen rausfinden / Datum angeben

Verfasst: Freitag 9. Januar 2015, 16:18
von Serpens66
sooo.. ich hab jetzt mal ausführlich getestet und mich dabei von der ein oder anderen Website ausgesperrt, weil ich vmerutlich zuviele anfragen verschickt hab :D
Bei meinen hier geposteten Versuchen habe ich diese webseiten aber dann weggelassen und darauf geachtet, dass keine solche Fehlermeldung mit in den Ergebnissen ist.

Die in beiden Fällen abgefragten URLS sehen so aus:

Code: Alles auswählen

URLS = ['http://www.foxnews.com/',
        'http://www.cnn.com/',
        'http://europe.wsj.com/',
        'http://www.bbc.co.uk/',
        'http://some-made-up-domain.com/',
        'http://python-forum.de/',
        'http://python-kurs.eu/',
        'http://abc.de/',
        'http://abc.de/',
        'http://abc.de/',
        'http://abd.de/',
        'http://abd.de/',        
        'http://abd.de/',        
        'http://abd.de/',
        'http://abe.de/',
        'http://abe.de/',        
        'http://abe.de/',        
        'http://abe.de/',        
        'http://abf.de/', 
        'http://abf.de/',    
        'http://abf.de/',    
        'http://abf.de/',    
        'http://abf.de/',    
        'http://abh.de/',   
        'http://abh.de/',
        'http://abh.de/',
        'http://abh.de/',
        'http://abh.de/',
        'http://abh.de/',
        'http://abi.de/',
        'http://abi.de/',
        'http://abi.de/',
        'http://abi.de/',
        'http://abi.de/']
Das Threading Skript sieht nun so aus:

Code: Alles auswählen

class Foo(threading.Thread):
    def __init__(self, url):
        threading.Thread.__init__(self)
        self.url = url      
        
    def load_url(self,url, timeout):
        conn = urllib.request.urlopen(url, timeout=timeout)
        return conn.readall()
   
    def run(self):
        try:
            data = self.load_url(self.url,60)
        except Exception as exc:
            print('%r generated an exception: %s' % (self.url, exc))
        else:
            print('%r page is %d bytes' % (self.url, len(data)))
 
if __name__ == "__main__":
    print("Mit THREADING {}".format(uhrzeit()))
    threads = list(map(Foo, URLS))
    for thread in threads:
        thread.start()
   
    for thread in threads:
        thread.join()

    print(uhrzeit())
und liefert folgende Ergebnisse (die ergebnisse der Websiten lasse ich außer beim ersten durchlauf mal weg, da es dieselben sind, in {} sind Anmerkungen von mir hier im Forum):
Mit THREADING Fri Jan 9 15:52:39 2015
'http://www.foxnews.com/' generated an exception: HTTP Error 404: Not Found
'http://some-made-up-domain.com/' generated an exception: <urlopen error [Errno 11001] getaddrinfo failed>
'http://abi.de/' page is 896 bytes
'http://abd.de/' page is 6006 bytes
'http://abe.de/' page is 449 bytes
'http://abd.de/' page is 6006 bytes
'http://abe.de/' page is 449 bytes
'http://abe.de/' page is 449 bytes
'http://abe.de/' page is 449 bytes
'http://abd.de/' page is 6006 bytes
'http://abi.de/' page is 896 bytes
'http://abi.de/' page is 896 bytes
'http://abi.de/' page is 896 bytes
'http://abi.de/' page is 896 bytes
'http://abd.de/' page is 6006 bytes
'http://abc.de/' page is 4232 bytes
'http://abc.de/' page is 4232 bytes
'http://python-kurs.eu/' page is 17646 bytes
'http://www.bbc.co.uk/' page is 102029 bytes
'http://abf.de/' page is 7468 bytes
'http://abf.de/' page is 7468 bytes
'http://abf.de/' page is 7468 bytes
'http://abf.de/' page is 7468 bytes
'http://abf.de/' page is 7468 bytes
'http://python-forum.de/' page is 35140 bytes
'http://abc.de/' page is 4232 bytes
'http://www.cnn.com/' page is 189025 bytes
'http://europe.wsj.com/' page is 238476 bytes
'http://abh.de/' page is 86180 bytes
'http://abh.de/' page is 86180 bytes
'http://abh.de/' page is 86179 bytes
'http://abh.de/' page is 86180 bytes
'http://abh.de/' page is 86180 bytes
'http://abh.de/' page is 86180 bytes
Fri Jan 9 15:52:41 2015 {also 2 sekunden}
______________________________________
Mit THREADING Fri Jan 9 15:53:18 2015
{...}
Fri Jan 9 15:53:21 2015 {also 3 sekunden}
______________________________________
Mit THREADING Fri Jan 9 15:53:54 2015
{...}
Fri Jan 9 15:53:58 2015 {also 4 sekunden}
Das "concurrent.futures.ThreadPoolExecutor" Skript sieht so aus (also bis auf die anzahl der worker, so wie in der doku):

Code: Alles auswählen

# Retrieve a single page and report the url and contents
def load_url(url, timeout):
    conn = urllib.request.urlopen(url, timeout=timeout)
    return conn.readall()

# We can use a with statement to ensure threads are cleaned up promptly
print("Mit FUTURES {}".format(uhrzeit()))
with concurrent.futures.ThreadPoolExecutor(max_workers=34) as executor:
    # Start the load operations and mark each future with its URL
    future_to_url = {executor.submit(load_url, url, 60): url for url in URLS}
    for future in concurrent.futures.as_completed(future_to_url):
        url = future_to_url[future]
        try:
            data = future.result()
        except Exception as exc:
            print('%r generated an exception: %s' % (url, exc))
        else:
            print('%r page is %d bytes' % (url, len(data)))
print(uhrzeit())
Das Ergebnis kürze ich mal ab:
Es waren bei allen drei Versuchen immer 3 sekunden.

Ich bin mir unsicher, was ich nun bei der Anzahl der worker schreiben muss.. Denn mit 17 workern hat es auch nur 3 sekunden gedauert. Mit 5 workern dann immerhin 4 sekunden und mit 1worker 12 sekunden. Ich dachte ich muss für jede Abfrage einen worker haben (bei 34 links also 34 worker? )


Tja...
threads -> 2,3 und 4 sekunden
"concurrent.futures.ThreadPoolExecutor" -> immer 3 sekunden

was ist nun besser ? :D Bei letzterem weiß ich noch nicht wie es funktioniert und wie man was schreiben muss. Ich könnte es also nicht ohne weiteres in unser spam, eggs, ham Beispiel umschreiben.. und das missfällt mir =/

Re: Durchlaufzeit von Funktionen rausfinden / Datum angeben

Verfasst: Samstag 10. Januar 2015, 16:09
von Sirius3
@Serpens66: Wieso erwartest Du Zeitunterschiede? Beide Beispiele setzen Threads zur Parallelisierung ein, nur die Interfaces sind total verschieden. futures haben den Vorteil, dass man sie einfacher in einen linearen Programmablauf einbauen und quasi wie Funktionen verwenden kann.

Hier übrigens das Beispiel mit asyncio:

Code: Alles auswählen

import asyncio
import aiohttp

@asyncio.coroutine
def read_url(url):
    conn = yield from aiohttp.request('get', url)
    return url, (yield from conn.read())

def main():
    tasks = [read_url(url) for url in URLS]
    for task in asyncio.as_completed(tasks):
        try:
           url, page = yield from task
           print("%s page is %d bytes" % (url, len(page)))
        except Exception as ext:
           print("Exception: %s" % ext)

loop = asyncio.get_event_loop()
loop.run_until_complete(main())

Re: Durchlaufzeit von Funktionen rausfinden / Datum angeben

Verfasst: Samstag 10. Januar 2015, 17:02
von Serpens66
@Sirius3: vielen dank für das Beispiel :)

Ich erwarte Unterschiede in der Zeit, weil hier ja behauptet wird, das eine sei besser geeignet als das andere :D Und ich möchte für mich selber sehen, was nun für meine Zwecke am besten ist. Die Zeit ist das einzige, was mir einfällt, was ich messen könnte, um die Unterschiede festzustellen.
Ich möchte die Unterschiede sehen, damit ich entscheiden kann, welches ich nun für mein Skript verwende.

Habe jetzt Thread gewählt und es für mein Zwecke verwendet. Hat ne Weile gedauert, aber jetzt scheint dabei alles zu funktionieren :)

Wenn du sagst, dass es keine zeitlichen Unterschiede gibt, was ist es dann, was mehr für das Eine und gegen das Andere spricht?

edit1: sehe gerade zu futures nennst du schon einen vorteil, danke :) Das war auch mein Gedanke, dass es leichter einzubauen ist (danke an pillmuncher für den Muster Pseudocode). Allerdings schreibt pillmuncher ja auch, dass man tatsächlich aber noch ThreadPoolExecutor.map() verwenden muss, was doch letzlich auf denselben (oder zumindest ähnlich hohen) Aufwand rauslaufen würde (nämlich auf eine funktion außerhalb des linearen Ablaufs zu verweisen), wie die Sache mit Threading, oder nicht?


Mein threading Skript sieht nun übrigens so aus (def parallel befindet sich in der "Boerse2Rock"-Klasse und kann halt jederzeit mit den gewünschten aufgaben aufgerufen werden... noch werden die ergebnisse einfach nur in eine liste geklatscht und geprintet, mal gucken wie ich das dann noch weiter mache) :

Code: Alles auswählen

    #sorgt dafür, dass übergebene Aufgaben parallel erledigt werden! (für aufgabennamen siehe multithread klasse)
    def parallel(self,aufgabe1, aufgabe2, aufgabe3=0, aufgabe4=0, aufgabe5=0, aufgabe6=0, aufgabe7=0):
        
        print("Zeit direkt bei parallel aufruf: {}".format(uhrzeit()))
        aufgabenliste = [aufgabe1, aufgabe2, aufgabe3, aufgabe4, aufgabe5, aufgabe6, aufgabe7]
        
        #jetzt noch alle nullen entfernen
        while 0 in aufgabenliste:
            aufgabenliste.remove(0)        
         
        threads = list(map(Multithread, aufgabenliste))
        for thread in threads:
            thread.start()
       
        for thread in threads:
            thread.join()
       
        print(list(thread.result for thread in threads))
        print("Zeit wenn fertig: {}".format(uhrzeit()))
    
# Klasse zum parallelierisern
class Multithread(threading.Thread):
    def __init__(self, aufgabe):
        threading.Thread.__init__(self)
       
        self.aufgabe = aufgabe      
        self.result = None  
        
    def run(self):
        if self.aufgabe == "MyBalanceEUR_boerse2":
            result = Boerse2Rock().get_balance("boerse2","EUR")
        if self.aufgabe == "MyBalanceEUR_rock":
            result = Boerse2Rock().get_balance("TheRock","EUR")
        if self.aufgabe == "FullOrderBook_rock":
            result = Boerse2Rock().get_orderbook("TheRock","BTCEUR")
        if self.aufgabe == "FullOrderBook_boerse2":
            result = Boerse2Rock().get_orderbook("boerse2","BTCEUR",10)
        if self.aufgabe == "GetTicker_boerse2":
            result = Boerse2Rock().get_ticker_exchangepair("boerse2","BTCEUR")
        if self.aufgabe == "GetTicker_rock":
            result = Boerse2Rock().get_ticker_exchangepair("TheRock","BTCEUR")
        self.result = result       
        return 1

edit2:
ich merke gerade, dass die aufgabenart mithilfe von festgelegten Namen festzulegen vllt doch nicht so günstig ist... Hier sind das meiste ja nur Anfragen, die nur wenige Paramenter benötigen. Aber wenn ich nun z.b eine Kauforder einstellen will, muss ich viele Parameter und vorallem auch den Preis nennen. Das funktioniert mit dieser Namensvergabe dann also schonmal nicht.

D.h ich muss ich jetzt überlegen, wie ich etwas parallel laufen lasse, aber dennoch alle gewünschten Paramter übergeben kann...
Fällt euch da was ein? Ich würde jetzt vermutlich auf Klasseninterne Variablen zurückgreifen. Z.b eine self.preis Variable, die kurz vor dem Aufruf von "parallel(kaufebtc_1, kaufebtc_2)" eingestellt wird, damit die dann wissen zu welchem Preis.

Re: Durchlaufzeit von Funktionen rausfinden / Datum angeben

Verfasst: Samstag 10. Januar 2015, 18:19
von BlackJack
@Serperns66: Geschwindigkeitsunterschiede beim *warten* sind irgendwie nicht wirklich zu erwarten, egal welche Technik da letztendlich wartet. Der Unterschied ist bei der Benutzung, ob man sich mit `Thread`\s auf dem Level herum schlägt das einem das Betriebssystem bietet, oder ob man etwas nimmt was einem viel Arbeit für so einen Standardfall schon abnimmt. Zum Beispiel das mit dem `map()`: Das musst Du nicht benutzen, Du kannst Dir das auch selber mit Schleifen schreiben, aber warum willst Du Dir diesen Mehraufwand geben wenn es dass doch schon fertig gibt‽

Warum bekommt `parallel()` keine Liste als Argument? Dann wird die Implementierung deutlich einfacher und die Benutzung deutlich flexibler.

Das mit der `self.aufgabe` ist unnötig umständlich. Anstelle dieser ganzen Zeichenketten die da verglichen werden wäre es viel einfacher und flexibler das die Aufgabe eine Funktion oder Methode ist die dann ohne irgendetwas zu prüfen einfach ausgeführt wird. Dann musst Du noch Ausnahmen ordentlich behandeln, und hey Du hast `concurrent.futures` Ansatzweise nachgebaut statt das einfach zu verwenden.

Die `Thread.run()`-Methode sollte nichts zurück geben. Das wird nirgends benutzt und ist deshalb total sinnfrei, aber verwirrend weil der Leser sich fragt warum das dort steht.

Re: Durchlaufzeit von Funktionen rausfinden / Datum angeben

Verfasst: Samstag 10. Januar 2015, 18:32
von Serpens66
@BlackJack:
danke :)
BlackJack hat geschrieben:Warum bekommt `parallel()` keine Liste als Argument? Dann wird die Implementierung deutlich einfacher und die Benutzung deutlich flexibler.
auf die Idee bin ich nicht gekommen :D das macht die ganze Sache deutlich einfacher und ich bin dann auch nicht auf maximal 10 Aufgaben beschränkt (wegen dem 10 argumente limit)... und ich kann alle nötigen Argumente übergeben, stimmt :)
BlackJack hat geschrieben: Das mit der `self.aufgabe` ist unnötig umständlich. Anstelle dieser ganzen Zeichenketten die da verglichen werden wäre es viel einfacher und flexibler das die Aufgabe eine Funktion oder Methode ist die dann ohne irgendetwas zu prüfen einfach ausgeführt wird. Dann musst Du noch Ausnahmen ordentlich behandeln, und hey Du hast `concurrent.futures` Ansatzweise nachgebaut statt das einfach zu verwenden.
Ja, das hab ich eben zeitgleich zu deinem Post noch unter edit2 reineditiert, dass diese Namensvergebung mit Zeichenketten nicht das wahre ist...
Das heißt im Fall von "MyBalanceEUR_boerse2", übergebe ich als Aufgabe stattessen gleich:
"Boerse2Rock().get_balance("boerse2","EUR")" ? Da stellt sich mir dann nur die Frage, wann diese Funktion dann ausgeführt wird.. soweit ich weiß würde es so gleich beim Übergeben schon ausgeführt werden und nur der return Wert ankommen, wodurch es nicht mehr parallelgeschaltet wäre, oder? Wobei, wenn man es als String übergibt, unterbindet man das... und ausführen tue ich es dann mit "result = eval(aufgabe1)" ?
Freut mich, dass ich `concurrent.futures` nun ansatzweise nachgebaut habe :D xD Naja, so verstehe ich wenigstens, wie das alles funktioniert :)
BlackJack hat geschrieben: Die `Thread.run()`-Methode sollte nichts zurück geben. Das wird nirgends benutzt und ist deshalb total sinnfrei, aber verwirrend weil der Leser sich fragt warum das dort steht.
ja stimmt, ich war mir unsicher, ob der return Wert irgendwo verwendet wird, hatte erst "return result" da stehen und hatte zum testen, ob noch dasselbe ergebnis rauskommt, dann return 1 draus gemacht und festgestellt, dass es egal ist was ich returne, nur vergessen es dann zu löschen :)

Edit:
Wenn ich jetzt die übergebene string-Funktion mit eval() ausführe, dann habe ich ja ein Problem mit den Parametern in dieser string-Funktion (weil diese variablen, welche nun parameter sind, an der auszuführenden Stelle evlt nicht bekannt sind). Ich nehme mal an, dass für diesen Fall die Globals und Locals aus der eval() Funktion da sind? Wie wende ich das korrekt an?
edit2: oder muss ich hier exec() verwenden?

Re: Durchlaufzeit von Funktionen rausfinden / Datum angeben

Verfasst: Samstag 10. Januar 2015, 18:44
von Sirius3
@Serpens66: natürlich darfst Du die Funktion für die Aufgabe nicht direkt aufrufen, aber Strings bringen Dich da auch nicht weiter. Schau Dir einfach mal an, wie es concurrent.futures' submit macht.

Re: Durchlaufzeit von Funktionen rausfinden / Datum angeben

Verfasst: Samstag 10. Januar 2015, 18:47
von EyDu
Und bei der Gelegenheit vergisst du gleich wieder, dass es eval und exec gibt. Die lösen keine Probleme, die schaffen höchstens welche.

Re: Durchlaufzeit von Funktionen rausfinden / Datum angeben

Verfasst: Samstag 10. Januar 2015, 18:47
von Serpens66
Sirius3 hat geschrieben:@Serpens66: natürlich darfst Du die Funktion für die Aufgabe nicht direkt aufrufen, aber Strings bringen Dich da auch nicht weiter. Schau Dir einfach mal an, wie es concurrent.futures' submit macht.
helfen strings die ich dann mit eval() oder exec() ausführe wirklich nicht?
Wo sehe ich denn, wie es concurrent.futures' submit macht? Hier sieht man die interne Funktionsweise glaube ich nicht, oder? https://docs.python.org/3/library/concu ... tor.submit

edit: okay, also eval und exec vergessen, wird gemacht:D

edit2: ah man sieht es vermutlich im SourceCode, ich schaus mir mal an :)

Re: Durchlaufzeit von Funktionen rausfinden / Datum angeben

Verfasst: Samstag 10. Januar 2015, 19:00
von Sirius3
@Serpens66: Ein erster Hinweis ist schon der Funktionsaufruf: submit(fn, *args, **kwargs)
An passender Stelle kannst Du dann die Funktion über

Code: Alles auswählen

fn(*args, **kwargs)
aufrufen.

Re: Durchlaufzeit von Funktionen rausfinden / Datum angeben

Verfasst: Samstag 10. Januar 2015, 19:33
von pillmuncher
Serpens66 hat geschrieben:Allerdings schreibt pillmuncher ja auch, dass man tatsächlich aber noch ThreadPoolExecutor.map() verwenden muss
Öh, äh, nein, das ist ein Missverständnis. Was ich meinte, war, dass es Futures für Threads und Prozesse gibt. Letztere startet man über einen ProcessPoolExecutor und erstere über einen ThreadPoolExecutor. Die map() Methode kann man verwenden, wenn sie zum Problem passt, und das erschien mir so. Du musst sie aber nicht verwenden.

Re: Durchlaufzeit von Funktionen rausfinden / Datum angeben

Verfasst: Samstag 10. Januar 2015, 19:49
von Serpens66
pillmuncher hat geschrieben:
Serpens66 hat geschrieben:Allerdings schreibt pillmuncher ja auch, dass man tatsächlich aber noch ThreadPoolExecutor.map() verwenden muss
Öh, äh, nein, das ist ein Missverständnis. Was ich meinte, war, dass es Futures für Threads und Prozesse gibt. Letztere startet man über einen ProcessPoolExecutor und erstere über einen ThreadPoolExecutor. Die map() Methode kann man verwenden, wenn sie zum Problem passt, und das erschien mir so. Du musst sie aber nicht verwenden.
achso...
also was ich jetzt meinte ist, dass ich auch mit der concurret.futures Methode außerhalb meines linearen ablaufs, die einzelnen aufgaben definieren muss. Ich kann sie nicht einfach innerhalb des with Blocks auflisten.
Oder kann ich das doch?
Vllt wäre ein Beispiel auf meine Anwendung hilfreich, kannst du da was schreiben? Ich verstehe nämlich noch nicht, wie ich es auf meine Anwedung anwende =/ wie man sieht mache ich es mir aktuell deutlich komplizierter, als es sein müsste und zudem wird es fehleranfälliger sein =/

Edit:
ist stelle es mir also so vor:

Code: Alles auswählen

future = Future(action)   
get_balance(args1)
get_ticker(args2)
result = future.get_result()
das wird dann ohne weitere funktionen parallel ausgeführt? Falls ja stellt sich mir nur die Frage, was ich da nun genau schreibe, zb. anstelle von "future= Future(action)".
Ich werde aus dem URLS-Beispiel der Doku nicht schlau, wie ich das nun auf meinen Fall anwenden muss.



Sirius3 hat geschrieben:@Serpens66: Ein erster Hinweis ist schon der Funktionsaufruf: submit(fn, *args, **kwargs)
An passender Stelle kannst Du dann die Funktion über

Code: Alles auswählen

fn(*args, **kwargs)
aufrufen.
ich hab es jetzt so geschrieben (die Klasse über parallel heißt jetzt "TheTest", weil ich es erstmal in meinem testskript durchprobiert habe):

Code: Alles auswählen

class TheTest():

    def __init__(self):
        self.var = None  # da es nicht geht, weiter geht, ohne iwas zu schreiben, definieren wir eine beliebige variable
        # für thetest wird nichts andres gebraucht

    """hier sind auch die ganzen funktionen get_balance usw definiert"""

    def parallel(self,aufgabenliste):
        
        threads = list(map(Multithread, aufgabenliste))
        for thread in threads:
            thread.start()
       
        for thread in threads:
            thread.join()
       
        print(list(thread.result for thread in threads))    

    def machwas(self):
        self.args1 = ["Kraken","ZEUR"]
        self.args2 = ["TheRock","EUR"]
        self.parallel(["TheTest().get_balance(*args1)","TheTest().get_balance(*args2)"]) 
        # hier weiß ich nicht, welche Namen ich verwenden muss, um auf die in machwas definierten Werte zu kommen.
     
class Multithread(threading.Thread):
    def __init__(self, aufgabe):
        threading.Thread.__init__(self)
       
        self.aufgabe = aufgabe      
        self.result = None  
        
    def run(self):
        result = eval(self.aufgabe)
        self.result = result       

Ich habe an Namen für args1 im Aufruf der parallel funktion schon probiert:
*TheTest().machwas().self.args1
*TheTest().machwas().args1
*TheTest().machwas.args1
*TheTest().args1
*TheTest().self.args1
*TheTest().self.machwas().args1
*TheTest().self.machwas().self.args1 (hier hätte ich gedacht, dass es klappen muss)

aber nichts davon klappt wie ich möchte... am nächsten kommt noch *TheTest().self.args1 , das findet es aber nur, wenn ich self.args1 in der init-funktion von TheTest definiere... ich weiß nicht, wie ich auf den Wert in machwas() komme.

Abgesehen von diesem Problem habe ich jetzt natürlich "eval()" genommen, weil ich aus dem Sourcecode von submit nicht rauslesen konnte, in welchem Format nun die Funktion übergeben wird, sodass sie nicht gleich ausgeführt wird.