Dataframes aus verschiedenen Prozessen zusammenfügen

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.
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

LukeNukem hat geschrieben: Donnerstag 8. Juli 2021, 16:12 Nun könnte man zwar vermuten, daß die zweite Variante eine neue Speicherallokation provoziert, allerdings... einerseits optimiert Python hier schon ziemlich gut (warum gibt es eigentlich das Modul "copy"?) und auf der anderen Seite hat da womöglich auch das Betriebssystem bzw. dessen Speicherverwaltung noch etwas beizutragen, etwa mit Copy-On-Write und Same-Page-Merging.
Ich weiß nicht, welche Vorstellungen Du da hast. Dir sagt der Begriff "Referenz" etwas?
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

LukeNukem hat geschrieben: Donnerstag 8. Juli 2021, 16:12 das Dumme ist halt, daß ich in den letzten acht Jahren beruflich wenig anderes gemacht habe als Massendatenverarbeitung unter Echtzeitbedingungen, genauer: die Verarbeitung von Transaktionsdaten zur Betrugsdetektion und -prävention. Wenn man so etwas über längere Zeiträume hinweg macht, dann gewinnt man eine... ziemlich innige Beziehung dazu, was eine Skriptsprache auf dem System und was das System dann auf der Hardware macht. Insofern habe ich vielleicht ein bisschen Erfahrung in Randbereichen, die die meisten anderen Entwickler vielleicht nicht jeden Tag sehen, und versuche meine Erfahrungen aus diesen Bereichen hier einzubringen.
Massendaten-Verarbeitung mit Python als Randbereich anzupreisen, lässt schon tief blicken. Das macht dich nicht zum Guru und dies zeigen auch deine Aussagen hier im Thread. Du scheinst dich ja echt sehr oft missverständlich auszudrücken. Oder will sich vielleicht jemand herausreden, wenn er korrigiert wird...? :o
mirko3107
User
Beiträge: 75
Registriert: Freitag 23. April 2021, 15:42

Hab eben festgestellt, dass sich mein Eingangsdataframe nicht von meinem Ausgangsdataframe unterscheidet, es werden quasi keine Werte überschrieben.
Das gleiche Script mit Multiprocessing funktioniert hingegen.

Code: Alles auswählen

def yahoo():
    watch = pd.read_csv("watch.csv", usecols=['Ticker', 'Name', 'Price', 'Change', 'Cap', 'EPS', 'Volumen', '52Whigh', '52Wlow', 'Rating'])
    rows = len(watch.index)
    while True:
        run = time.time()
        for i in range(0, rows):
            try:
                ticker = watch['Ticker'].values[i]
                quote_url = 'https://query1.finance.yahoo.com/v7/finance/quote?symbols='+ticker
                quote_req = requests.get(quote_url)
                change = round(quote_req.json()['quoteResponse']['result'][0].get('regularMarketChangePercent', 0),2)
                price = round(quote_req.json()['quoteResponse']['result'][0].get('regularMarketPrice', 0),2)
                volume = quote_req.json()['quoteResponse']['result'][0].get('regularMarketVolume', 0)
                W52high = round(quote_req.json()['quoteResponse']['result'][0].get('fiftyTwoWeekHigh', 0),2)
                W52low = round(quote_req.json()['quoteResponse']['result'][0].get('fiftyTwoWeekLow', 0),2)
                rat1 = quote_req.json()['quoteResponse']['result'][0].get('averageAnalystRating', 'None')
                rating=''
                for i in rat1:
                    if i.isalpha():
                        rating = "".join([rating, i])
                if 'epsCurrentYear' in quote_req.json()['quoteResponse']['result'][0]:
                    eps = round(quote_req.json()['quoteResponse']['result'][0].get('epsCurrentYear', 0),2)
                else:
                    eps = '0'
                cap = round(quote_req.json()['quoteResponse']['result'][0].get('marketCap', 0)/1000000000, 2)
                #print(ticker,price,change,cap,eps,volume,W52high,W52low,rating)
                watch.at[i, 'Price'] = price
                watch.at[i, 'Change'] = change
                watch.at[i, 'Cap'] = cap
                watch.at[i, 'EPS'] = eps
                watch.at[i, 'Volumen'] = volume
                watch.at[i, '52Whigh'] = W52high
                watch.at[i, '52Wlow'] = W52low
                watch.at[i, 'Rating'] = rating
            except (KeyError, IndexError, RemoteDataError) as error:
                print(f"Failed reading {ticker}: {error}")
                pass
        watch.to_csv('pack1.csv', header=True, index=False)
        time.sleep(600)
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@LukeNukem: Der amortisierte „worst case“ hat nichts mit der Grösse des Wörterbuchs zu tun. Ich weiss nicht wo Du das aus der Wikiseite heraus liest. Der betrifft *jede* Wörterbuchgrösse.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
rogerb
User
Beiträge: 878
Registriert: Dienstag 26. November 2019, 23:24

Code: Alles auswählen

import aiohttp
import asyncio
import time
import statistics

loop = asyncio.get_event_loop()


async def get_result():
    async with aiohttp.ClientSession() as session:
        async with session.get(
            "https://query1.finance.yahoo.com/v7/finance/quote?symbols=GOOG"
        ) as response:
            response.raise_for_status()
            return await response.json()


async def no_data_storage():
    await asyncio.gather(*[get_result() for _ in range(1000)])


async def with_data_storage():
    response = await asyncio.gather(*[get_result() for _ in range(1000)])


def measure(measure_func):
    times = []
    for _ in range(10):
        start = time.perf_counter()
        loop.run_until_complete(measure_func())
        delta = time.perf_counter() - start
        times.append(delta)
        print(f"{delta:10.3f} s")

    print(f"Durchschnitt: {statistics.mean(times):0.3f}")


print("Ohne Speichern")
measure(no_data_storage)
print()
print("Mit Speichern")
measure(with_data_storage)
Ausgabe:

Code: Alles auswählen

Ohne Speichern
    14.601 s
    27.252 s
    20.859 s
    43.963 s
    33.140 s
    28.015 s
    16.654 s
    18.356 s
    15.417 s
    20.989 s
Durchschnitt: 23.925

Mit Speichern
    21.014 s
    20.790 s
    27.653 s
    19.263 s
    19.793 s
    29.764 s
    27.843 s
    18.609 s
    28.514 s
    27.414 s
Durchschnitt: 24.066
10 mal 1000 Anfragen an Yahoo-Finance. Beim zweiten Durchlauf werden die JSON-Daten jeweils zur möglichen Weiterverarbeitung in einen Dictionary gespeichert.
LukeNukem
User
Beiträge: 232
Registriert: Mittwoch 19. Mai 2021, 03:40

snafu hat geschrieben: Donnerstag 8. Juli 2021, 19:37 Massendaten-Verarbeitung mit Python als Randbereich anzupreisen,
In dem genannten Umfeld und dort insbesondere im Echtzeitbereich gibt's da nicht so viele.
snafu hat geschrieben: Donnerstag 8. Juli 2021, 19:37 Das macht dich nicht zum Guru
Hat auch keiner behauptet, oder?
snafu hat geschrieben: Donnerstag 8. Juli 2021, 19:37 Du scheinst dich ja echt sehr oft missverständlich auszudrücken.
Es würde die Mißverständnisse wesentlich reduzieren, wenn Du meine Ausführungen vollständig läsest und Deine Energie in deren Verständnis investieren würdest, anstatt mit Strohpuppen zu "argumentieren".
snafu hat geschrieben: Donnerstag 8. Juli 2021, 19:37 Oder will sich vielleicht jemand herausreden, wenn er korrigiert wird...? :o
Na klar. ;-)
LukeNukem
User
Beiträge: 232
Registriert: Mittwoch 19. Mai 2021, 03:40

__blackjack__ hat geschrieben: Donnerstag 8. Juli 2021, 22:32 @LukeNukem: Der amortisierte „worst case“ hat nichts mit der Grösse des Wörterbuchs zu tun. Ich weiss nicht wo Du das aus der Wikiseite heraus liest. Der betrifft *jede* Wörterbuchgrösse.
Tatsächlich hatte es in älteren Python-Versionen sogar etwas mit den Inhalten der Schlüssel zu tun und hat bis heute etwas mit der Schlüssellänge zu tun. Und wenn der Worst Case O(n) ist, dann hat die Größe des Schlüsslraums (dieses ominöse n in O(n)) natürlich eine entsprechend größere Auswirkung auf die Performance, wenn der Worst Case eintritt.

Aber egal, Butter bei die Fische: ich hab' mir mal den Code des TO genommen (func1()), dann meine erste Optimierung mit der .json()-Methode umgesetzt (func2()) und am Ende auch meinen Optimierungsvorschlag für die Dictionary-Zugriffe implementiert (func5()), und dann je fünfzig Durchläufe der betreffenden Funktionen gemessen. Ergebnis:

Code: Alles auswählen

func1() = count: 50, alltime:  66390.4 µs
func2() = count: 50, alltime:   1510.2 µs
func5() = count: 50, alltime:   1339.9 µs
Es stellt sich heraus, was zu erwarten war: die .json()-Methode nur einmal aufzurufen, hat natürlich den größten Einfluß. Trotzdem finde ich es für so ein paar popelige Daten schon ziemlich bemerkenswert, daß die angeblich so schnellen Dictionary-Zugriffe immerhin gute 11% Laufzeitunterschied ausmachen (Dell E5580 mit i7-7820HQ und 32 GB RAM unter Kubuntu 20.04 LTS mit Linux 5.8.0-59). O(1) ist eben doch nicht gleich 0, was meinst Du?
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Das hatte ich erwartet, dass jemand, der "Echtzeit" mit Python macht, sich freut, wenn er 40µs pro Durchlauf sparen kann.
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

"Premature Optimization, the root of all evil." Ausser es handelt sich um "premature micro-optimization for the sole purpose to not admit that I justified my remarks in the wrong way is A-ok!".

Niemand, wirklich niemand hier, hat behauptet, dass es nicht besser waere, solche geschachtelten Zugriffe zu vermeiden. Nur eben nicht, weil sie so unfassbar teuer waeren, wie du behauptest. Sondern weil sie schlechter lesbar, DRY-verletzend, und schlecher wartbar sind.
LukeNukem
User
Beiträge: 232
Registriert: Mittwoch 19. Mai 2021, 03:40

__deets__ hat geschrieben: Freitag 9. Juli 2021, 09:30 "Premature Optimization, the root of all evil."
Nix "premature". "Measure, don't guess".
__deets__ hat geschrieben: Freitag 9. Juli 2021, 09:30 Ausser es handelt sich um "premature micro-optimization for the sole purpose to not admit that I justified my remarks in the wrong way is A-ok!".
Na klar.
__deets__ hat geschrieben: Freitag 9. Juli 2021, 09:30 Niemand, wirklich niemand hier, hat behauptet, dass es nicht besser waere, solche geschachtelten Zugriffe zu vermeiden. Nur eben nicht, weil sie so unfassbar teuer waeren, wie du behauptest.
Niemand, wirklich niemand hat behauptet, daß diese Zugriffe "unfassbar teuer waeren", wie Du behauptest. Meine Aussage war:
LukeNukem hat geschrieben: Mittwoch 7. Juli 2021, 19:01 Dictionaries sind jetzt auch nicht unbedingt das performanteste Feature von Python.
Genau das habe ich geschrieben. Und mittlerweile belegt. Elf Prozent Laufzeitdifferenz finde ich für ein Feature, dessen Zeitkomplexität O(1) hier als "so schnell, daß es vernachlässigbar ist" verstanden zu werden und dessen Worst Case O(n) geflissentlich übersehen zu werden scheint, immer noch enorm. Dabei sagt die Zeitkomplexität O(1) natürlich gar nichts über den tatsächlichen Zeitbedarf eines Zugriffs, sondern nur, daß die tatsächlich benötigte Zeit unabhängig von der Anzahl der Elemente ist. Also, im Idealfall. Und unter gleichbleibenden Randbedingungen.

Obendrein war dieser Part ja nur ein Teil meiner Aussage. Der andere Teil betraf die wiederholten json()-Aufrufe, und die machen einen Faktor von etwa 40 aus. Verzeihung, aber... es kann doch wirklich nicht so schwierig sein, mehrere zusammenhängende Aussagen in einem Absatz von nicht einmal zwei Zeilen zu verstehen, oder doch? Und dann bin ich unerklärlicherweise nicht auf das Zeug eingegangen, der einigen hier so wichtig zu sein scheint, wie DRY-Principle, Lesbarkeit und Wartbarkeit, sondern habe expizit die Frage des TO adressiert, nämlich die schlechte Performance, die er beklagt hat. Meine Güte, wie konnte ich nur! ;-)
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

LukeNukem hat geschrieben: Donnerstag 8. Juli 2021, 16:12 De facto ist es nun einmal auch so, daß wir gar nicht wissen, wie die Netzwerkanbindung des TO ist, wie die Serverseite aussieht, und, vor allem: wie die Daten aussehen. Aber das das hier:

Code: Alles auswählen

d['a']['b']['c'].get('eins')
d['a']['b']['c'].get(''zwei')
d['a']['b']['c'].get('drei')
d['a']['b']['c'].get('vier')
mehrmals dieselben Zugriffe auf dasselbe Dictionary macht, während

Code: Alles auswählen

dummy = d['a']['b']['c']
dummy.get('eins')
dummy.get(''zwei')
dummy.get('drei')
dummy.get('vier')
sich diesen Unfug spart, ist für einen Profi wie Dich sicherlich offensichtlich und dürfte mit wenigen Sekunden des Nachdenkens sogar einem Hobbyisten klar werden.
Da widerspreche ich auch nicht. Es ist allerdings kein wesentlich Faktor weil es andere Baustellen gibt der mehrere Größenordnungen langsamer sind. Wenn ich Performance optimiere fange ich nicht bei dem Teil an der sowieso schon am schnellsten sein wird.
Nun könnte man zwar vermuten, daß die zweite Variante eine neue Speicherallokation provoziert[...]
Könnte man wenn man von Python keine Ahnung hat, aber da keine Kopie angelegt wird sondern nur eine Referenz führt dass garantiert nicht zu einer Allokation.
[...], allerdings... einerseits optimiert Python hier schon ziemlich gut (warum gibt es eigentlich das Modul "copy"?) und auf der anderen Seite hat da womöglich auch das Betriebssystem bzw. dessen Speicherverwaltung noch etwas beizutragen, etwa mit Copy-On-Write und Same-Page-Merging.
Das Copy Modul existiert um Objekte zu kopieren, ist größtenteils unnötig und spielt hier keine Rolle da es nicht benutzt wird (und auch nicht werden sollte). Das Betriebssystem hat da wenig beizutragen zum einen weil diese Optimierungen den Speicherverbrauch gering halten und sich auf die Laufzeit, was ja hier das Problem ist nicht auswirken, zum anderen funktioniert Copy-on-Write jetzt eher nicht so gut wenn man ständig in irgendwelche Objekte schreibt wie man dass bei Reference Counting so macht.
Darüber hinaus, bitte verzeih' den Widerspruch: Python nutzt unter der Haube selbstverständlich die ganz normale malloc(3)-Funktion. Daß Python dessen Benutzung stark optimiert (wie gesagt, think "copy"-Modul), ist diesseits bekannt. Aber trotzdem danke für den Hinweis, der für andere Leser vielleicht wertvoll ist.
CPython hat einen eigenen Memory Manager der für Allokationen genutzt wird. Der baut auf malloc auf und somit ist tief unter der Haube irgendwo ein malloc versteckt wird aber i.d.R. nicht passieren wenn man ein Objekt erstellt. Damit unterscheidet sich Python da wesentlich von Sprachen wie C, C++ oder Rust wo man bei einer Heap Allokationen normalerweise ein malloc hat. Das ist auch essentiell für die Performance einer solchen Sprache wo man anders als in C, C++ oder Rust nahezu alles auf der Heap statt auf dem Stack allokiert. Die JVM ist hier ein besonders gutes Beispiel, da die sich gleich beim Startup eine ganze Heap allokiert um zur Laufzeit möglichst nie malloc aufzurufen.
mirko3107
User
Beiträge: 75
Registriert: Freitag 23. April 2021, 15:42

Könnt ihr euren Streit nicht per PN klären?

@Topic: Mein Dataframe wird immer noch nicht beschrieben, hab alle möglichen Optionen probiert.
mirko3107
User
Beiträge: 75
Registriert: Freitag 23. April 2021, 15:42

mirko3107 hat geschrieben: Freitag 9. Juli 2021, 13:51 Könnt ihr euren Streit nicht per PN klären?

@Topic: Mein Dataframe wird immer noch nicht beschrieben, hab alle möglichen Optionen probiert.

Code: Alles auswählen

  Ticker                         Name   Price    Change           Cap    EPS   Earnings     IV Rating    Volumen  SMA200    RSI  Stoch  52Whigh  52Wlow  Weekly
0      A     Agilent Technologies Inc  148.98  0.107505  4.539390e+10   4.14  8/17/2021  22.64    buy    1973342  122.73  65.71  92.53   149.19   88.07   False
1     AA                   Alcoa Corp   36.47 -3.823830  6.809861e+09   4.19  7/15/2021  55.85    buy    8577484   25.84  52.18  81.14    44.42   10.43    True
2    AAL  American Airlines Group Inc   21.01 -2.188079  1.347546e+10  -8.49  7/22/2021  47.77   hold   23985527   18.32  31.37  17.21    26.09   10.63    True
3    AAP     Advance Auto Parts, Inc.  208.70 -1.113480  1.365710e+10  10.91  8/17/2021  26.62    buy     540639  172.21  66.23  95.21   211.16  131.90   False
4   AAPL                    Apple Inc  142.02  1.471847  2.369973e+12   5.20  7/27/2021  26.62    buy  108181793  125.56  69.22  96.87   145.09   89.14    True
A 149.58 0.5 45.39 4.14 148813 149.67 88.07 Buy
AA 37.75 6.76 7.05 4.27 2009404 44.42 10.43 Buy
AAL 20.9 2.7 13.41 -8.54 7809996 26.09 10.63 Hold
AAP 211.57 1.96 13.84 10.92 93008 212.35 131.9 Buy
AAPL 144.66 0.99 2414.03 5.18 25755981 145.09 89.14 Buy
  Ticker                         Name   Price    Change           Cap    EPS   Earnings     IV Rating      Volumen  SMA200    RSI  Stoch  52Whigh  52Wlow Weekly
0      A     Agilent Technologies Inc  148.98  0.107505  4.539390e+10   4.14  8/17/2021  22.64    buy    1973342.0  122.73  65.71  92.53   149.19   88.07  False
1     AA                   Alcoa Corp   36.47 -3.823830  6.809861e+09   4.19  7/15/2021  55.85    buy    8577484.0   25.84  52.18  81.14    44.42   10.43   True
2    AAL  American Airlines Group Inc   21.01 -2.188079  1.347546e+10  -8.49  7/22/2021  47.77   hold   23985527.0   18.32  31.37  17.21    26.09   10.63   True
3    AAP     Advance Auto Parts, Inc.  208.70 -1.113480  1.365710e+10  10.91  8/17/2021  26.62    buy     540639.0  172.21  66.23  95.21   211.16  131.90  False
4   AAPL                    Apple Inc  142.02  1.471847  2.369973e+12   5.20  7/27/2021  26.62    buy  108181793.0  125.56  69.22  96.87   145.09   89.14   True
LukeNukem
User
Beiträge: 232
Registriert: Mittwoch 19. Mai 2021, 03:40

DasIch hat geschrieben: Freitag 9. Juli 2021, 12:28 Es ist allerdings kein wesentlich Faktor weil es andere Baustellen gibt der mehrere Größenordnungen langsamer sind.
Selbstverständlich, gar keine Frage. Dennoch möchte ich zu bedenken geben: Multiprocessing und Multithreading sind relativ komplexe Geschichten, und... es erscheint mir einigermaßen schwierig, wenn ein offensichtlicher Anfänger mit solchen Dingen beschäftigt ist und sie sogar schon in einem Projekt benutzt, ohne zumindest die Basics erlernt und verstanden zu haben. Darum erschien und erscheint es mir in diesem Fall zielführender, erst einmal solche offensichtlichen Dinge glattzuziehen, in der (heimlichen) Hoffnung, daß das möglichst frühzeitig zu einem etwas bessen Verständnis führt.

Allerdings sehe ich in den letzten Jahren ohnehin einen Trend, daß viele Menschen gerne ein bestimmtes Problem lösen wollen, nichts fertiges und für ihren Anwendungsfall nutzbares finden und dann realisieren, daß sie wahrscheinlich ein eigenes Programm dafür schreiben müssen -- und sich dann nur sehr oberflächlich oder sogar gar nicht mit den Grundlagen der Programmierung oder der auserkorenen Sprache beschäftigen, sondern sich sofort auf ihr Problem stürzen in der Hoffnung, das mit dem Programmieren und der Sprache quasi "nebenbei" zu lernen. Nicht selten kopieren sie sich dann irgendwas aus dem Netz und basteln per Trial & Error dann so lange daran herum, gerne auch mit Hilfe von Foren wie diesem, bis sie etwas haben, das zwar irgendwie läuft und irgendetwas tut -- für oft recht beliebige Definitionen von "irgendwie", "irgendetwas", "läuft" und "tut" -- aber das sie nicht im Ansatz verstanden haben und ihnen früher oder später auf die Füße fällt. Aus verschiedenen Gründen habe ich tiefe Zweifel, daß das sonderlich zielführend ist... nicht zuletzt auch darum, weil ich derartige Diskussionen in mannigfaltigsten Ausführungen schon von Benutzern kenne, die sich -- mal so ganz nebenbei aus Neugierde -- ein Linux installieren, dann feststellen, daß es anders funktioniert als ihr gewohntes System, und dann manchmal über Stunden, in einigen Fällen auch über Tage, Wochen und sogar Monate hinweg über dieses doofe Linux ranten. Okay, zumindest jüngere Menschen schauen sich manchmal wenigstens einige Videos mit Tutorials auf populären Videoplattformen an -- und manche davon sind dabei sogar richtig schnell auf dem richtigen Gleis.
DasIch hat geschrieben: Freitag 9. Juli 2021, 12:28
Nun könnte man zwar vermuten, daß die zweite Variante eine neue Speicherallokation provoziert[...]
Könnte man wenn man von Python keine Ahnung hat,
Natürlich, deswegen ja auch der Konjunktiv. ;-)
DasIch hat geschrieben: Freitag 9. Juli 2021, 12:28 Das Copy Modul existiert um Objekte zu kopieren, ist größtenteils unnötig und spielt hier keine Rolle da es nicht benutzt wird (und auch nicht werden sollte).
Oh... neinneinein. Ich wollte mit dem kleinen Hinweis vielmehr darauf hinaus, daß Pythons Speicherverwaltung hin und wieder sogar etwas... überenthusiastisch optimiert. Jedenfalls in früheren Versionen -- ohne genauer hingeschaut zu haben, ist mein subjektiver Eindruck jedenfalls, daß die Optimierung immer besser funktioniert und deren gezielte Umgehung immer seltener notwendig wird. ;-)
DasIch hat geschrieben: Freitag 9. Juli 2021, 12:28 CPython hat einen eigenen Memory Manager der für Allokationen genutzt wird. Der baut auf malloc auf und somit ist tief unter der Haube irgendwo ein malloc versteckt wird aber i.d.R. nicht passieren wenn man ein Objekt erstellt.
Ja, klar. Skriptsprache halt, das machen andere ja ähnlich -- wenngleich (mein Eindruck) meistens nicht so stark optimiert wie in Python. Aber trotz aller Optimierungen und nifty tricks läuft natürlich auch Python in der Regel auf einer Hardware, und schon das geht nun einmal mit entsprechenden Limitierungen einher: Speichergrößen und -Bandbreite(n) der jeweiligen Speicher, ... und mit Ausnahme von Micropython läuft Python nun einmal meistens auf einem Betriebssystem mit einer Speicherverwaltung, die wiederum ihre eigenen Charakteristiken und Optimierungen mitbringt.
DasIch hat geschrieben: Freitag 9. Juli 2021, 12:28 Damit unterscheidet sich Python da wesentlich von Sprachen wie C, C++ oder Rust wo man bei einer Heap Allokationen normalerweise ein malloc hat. Das ist auch essentiell für die Performance einer solchen Sprache wo man anders als in C, C++ oder Rust nahezu alles auf der Heap statt auf dem Stack allokiert.
Hmmm... bei Rust auch? Hat Rust denn nicht auch eine eigene Speicherverwaltung mit Garbage Collection?
DasIch hat geschrieben: Freitag 9. Juli 2021, 12:28 Die JVM ist hier ein besonders gutes Beispiel, da die sich gleich beim Startup eine ganze Heap allokiert um zur Laufzeit möglichst nie malloc aufzurufen.
Hmmm, Java... eine Erfahrung, die ich gerne so schnell und nachhaltig wie möglich vergessen möchte. Daher vielen Dank für Deine Antwort, aber immer wenn Java erwähnt wird, muß ich dringend zu Youtube und das hier [1] anschauen... mittlerweile zum Glück nur noch höchstens zwei- oder dreimal, immerhin. ;-)

[1] https://www.youtube.com/watch?v=PUCgC_TukKg
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

LukeNukem hat geschrieben: Freitag 9. Juli 2021, 15:49Ich wollte mit dem kleinen Hinweis vielmehr darauf hinaus, daß Pythons Speicherverwaltung hin und wieder sogar etwas... überenthusiastisch optimiert. Jedenfalls in früheren Versionen -- ohne genauer hingeschaut zu haben, ist mein subjektiver Eindruck jedenfalls, daß die Optimierung immer besser funktioniert und deren gezielte Umgehung immer seltener notwendig wird.
Von welchen Optimierungen faselst Du denn da? Und wie oder was umgehst Du? Ich habe immer noch das Gefühl, dass Du noch nicht verstanden hast, was Referenzen sind.
LukeNukem
User
Beiträge: 232
Registriert: Mittwoch 19. Mai 2021, 03:40

mirko3107 hat geschrieben: Freitag 9. Juli 2021, 13:51 Könnt ihr euren Streit nicht per PN klären?
Bitte entschuldige, Du hast natürlich Recht.
mirko3107 hat geschrieben: Freitag 9. Juli 2021, 13:51 @Topic: Mein Dataframe wird immer noch nicht beschrieben, hab alle möglichen Optionen probiert.
Verzeihung, welcher Dataframe wird denn nicht beschrieben? Die einzelnen Dateframes aus Deinen Funktionen oder am Ende der "Gesamt-Dataframe", der aus jenen in Deinen Funktionen konkateniert werden soll? Was hast Du bereits ausprobiert, und inwiefern hat es nicht funktioniert? Gab es Fehlermeldungen, und wenn ja, welche? Und wie sieht der Code aus, mit dem Du es ausprobiert hast?
mirko3107
User
Beiträge: 75
Registriert: Freitag 23. April 2021, 15:42

Ich lese aus einer csv ein Dataframe, schreibe Werte in das Dataframe ( hatte ich jedenfalls gedacht) und am Ende sind alle Werte unverändert.

Die Funktion sieht so aus:

Code: Alles auswählen

def yahoo():
    watch = pd.read_csv("watch.csv", usecols=['Ticker', 'Name', 'Price', 'Change', 'Cap', 'EPS', 'Volumen', '52Whigh', '52Wlow', 'Rating'])
    print(watch.head(5))
    rows = len(watch.index)
    while True:
        for i in range(0, 5):
            try:
                ticker = watch['Ticker'].values[i]
                quote_url = 'https://query1.finance.yahoo.com/v7/finance/quote?symbols='+ticker
                quote_req = requests.get(quote_url)
                change = round(quote_req.json()['quoteResponse']['result'][0].get('regularMarketChangePercent', 0),2)
                price = round(quote_req.json()['quoteResponse']['result'][0].get('regularMarketPrice', 0),2)
                volume = quote_req.json()['quoteResponse']['result'][0].get('regularMarketVolume', 0)
                W52high = round(quote_req.json()['quoteResponse']['result'][0].get('fiftyTwoWeekHigh', 0),2)
                W52low = round(quote_req.json()['quoteResponse']['result'][0].get('fiftyTwoWeekLow', 0),2)
                rat1 = quote_req.json()['quoteResponse']['result'][0].get('averageAnalystRating', 'None')
                rating=''
                for i in rat1:
                    if i.isalpha():
                        rating = "".join([rating, i])
                if 'epsCurrentYear' in quote_req.json()['quoteResponse']['result'][0]:
                    eps = round(quote_req.json()['quoteResponse']['result'][0].get('epsCurrentYear', 0),2)
                else:
                    eps = '0'
                cap = round(quote_req.json()['quoteResponse']['result'][0].get('marketCap', 0)/1000000000, 2)
                print(ticker,price,change,cap,eps,volume,W52high,W52low,rating)
                time.sleep(0.5)
                watch.at[i, 'Price'] = price
                watch.at[i, 'Change'] = change
                watch.at[i, 'Cap'] = cap
                watch.at[i, 'EPS'] = eps
                watch.at[i, 'Volumen'] = volume
                watch.at[i, '52Whigh'] = W52high
                watch.at[i, '52Wlow'] = W52low
                watch.at[i, 'Rating'] = rating
            except (KeyError, IndexError, RemoteDataError) as error:
                print(f"Failed reading {ticker}: {error}")
                pass
        print(watch.head(5))
        watch.to_csv('watch2.csv', header=True, index=False, columns=['Ticker', 'Name', 'Price', 'Change', 'Cap', 'EPS', 'Volumen', '52Whigh', '52Wlow', 'Rating'])
        time.sleep(600)
Oben das Dataframe aus der CSV, dann die Werte, die reinsollen und unten das Dataframe, wie es wieder in die CSV geschrieben wird.

Code: Alles auswählen

  Ticker                         Name   Price    Change           Cap    EPS Rating    Volumen  52Whigh  52Wlow
0      A     Agilent Technologies Inc  148.98  0.107505  4.539390e+10   4.14    buy    1973342   149.19   88.07
1     AA                   Alcoa Corp   36.47 -3.823830  6.809861e+09   4.19    buy    8577484    44.42   10.43
2    AAL  American Airlines Group Inc   21.01 -2.188079  1.347546e+10  -8.49   hold   23985527    26.09   10.63
3    AAP     Advance Auto Parts, Inc.  208.70 -1.113480  1.365710e+10  10.91    buy     540639   211.16  131.90
4   AAPL                    Apple Inc  142.02  1.471847  2.369973e+12   5.20    buy  108181793   145.09   89.14
A 149.37 0.36 45.33 4.14 195631 149.71 88.07 Buy
AA 37.6 6.33 7.02 4.27 2698158 44.42 10.43 Buy
AAL 20.91 2.73 13.41 -8.54 9537317 26.09 10.63 Hold
AAP 211.65 2.0 13.85 10.92 118807 212.35 131.9 Buy
AAPL 145.06 1.27 2420.7 5.18 38741349 145.44 89.14 Buy
  Ticker                         Name   Price    Change           Cap    EPS Rating      Volumen  52Whigh  52Wlow
0      A     Agilent Technologies Inc  148.98  0.107505  4.539390e+10   4.14    buy    1973342.0   149.19   88.07
1     AA                   Alcoa Corp   36.47 -3.823830  6.809861e+09   4.19    buy    8577484.0    44.42   10.43
2    AAL  American Airlines Group Inc   21.01 -2.188079  1.347546e+10  -8.49   hold   23985527.0    26.09   10.63
3    AAP     Advance Auto Parts, Inc.  208.70 -1.113480  1.365710e+10  10.91    buy     540639.0   211.16  131.90
4   AAPL                    Apple Inc  142.02  1.471847  2.369973e+12   5.20    buy  108181793.0   145.09   89.14
mirko3107
User
Beiträge: 75
Registriert: Freitag 23. April 2021, 15:42

Fehlermeldung kommt keine.
LukeNukem
User
Beiträge: 232
Registriert: Mittwoch 19. Mai 2021, 03:40

mirko3107 hat geschrieben: Freitag 9. Juli 2021, 16:14 Ich lese aus einer csv ein Dataframe, schreibe Werte in das Dataframe ( hatte ich jedenfalls gedacht) und am Ende sind alle Werte unverändert.

Code: Alles auswählen

  Ticker                         Name   Price    Change           Cap    EPS Rating    Volumen  52Whigh  52Wlow
0      A     Agilent Technologies Inc  148.98  0.107505  4.539390e+10   4.14    buy    1973342   149.19   88.07
1     AA                   Alcoa Corp   36.47 -3.823830  6.809861e+09   4.19    buy    8577484    44.42   10.43
2    AAL  American Airlines Group Inc   21.01 -2.188079  1.347546e+10  -8.49   hold   23985527    26.09   10.63
3    AAP     Advance Auto Parts, Inc.  208.70 -1.113480  1.365710e+10  10.91    buy     540639   211.16  131.90
4   AAPL                    Apple Inc  142.02  1.471847  2.369973e+12   5.20    buy  108181793   145.09   89.14
Könntest Du diesen -- nur diesen -- Teil bitte einmal in eine CSV-Datei schreiben und sie hier als Code posten?
mirko3107
User
Beiträge: 75
Registriert: Freitag 23. April 2021, 15:42

Die gespeicherte CSV sieht genauso aus wie die geladene.

Code: Alles auswählen

Ticker,Name,Price,Change,Cap,EPS,Volumen,52Whigh,52Wlow,Rating
A,Agilent Technologies Inc,148.98,0.107505,45393903616.0,4.14,1973342.0,149.19,88.07,buy
AA,Alcoa Corp,36.47,-3.82383,6809860608.0,4.19,8577484.0,44.42,10.43,buy
AAL,American Airlines Group Inc,21.01,-2.1880789,13475456000.0,-8.49,23985527.0,26.09,10.63,hold
AAP,"Advance Auto Parts, Inc.",208.7,-1.11348,13657098240.0,10.91,540639.0,211.16,131.9,buy
AAPL,Apple Inc,142.02,1.4718473,2369972862976.0,5.2,108181793.0,145.09,89.14,buy
Antworten