Che Posted September 11, 2021 Report Posted September 11, 2021 Am facut un script in Python care preia de pe Yahoo Finance diverse date despre stocks. In total sunt vreo 53.000 de companii. Probleme: Cand se opreste curentul trebuie sa rulezi iarasi scriptul de la inceput. -> Am rezolvat deja asta. I-am facut un log si preia de la ultimul log. Daca nu pica curentul ci internetul atunci ori imi scrie niste fisiere goale in loc sa fie cu informatii. Cum pot rezolva asta din moment ce unele companii chiar nu au informatii dar cand se intampla asta scrie un fisier gol si la cele care au info? Tot la fel, poate sa pice internetul si in loc de fisiere goale se blocheaza la accesarea informatiilor curente si practic sta asa la nesfarsit chiar daca internetul si-a revenit el pur si simplu arata "retrieveing..." si ramane asa blocat. Cum se poate rezolva asta? O alta chestie este atunci cand de la prea multe requesturi (sau server maintenance - nu pot sti exact de la ce) se intampla exact ca mai sus adica ramane blocat. Cum fac sa rezolv asta? Scriptul este unul banal care se gaseste la prima cautare pe google si care foloseste yfinance ca si modul in Python si cu un for loop face requesturi pe yfinance.info pentru a lua informatiile. Ma gandesc ca ar trebui un fel de network management care sa isi dea seama cand a picat internetul sau cand este serverul down, in maintenance sau refuza conexiunea de la prea multe requesturi (chiar daca nu sunt cu frecventa mare cred ca te monitorizeaza si li se aprind niste triggers cand vad 30.000 de accesari doar de la tine. Nu vreau sa ma complic cu proxy sau VPN. Apropo, cand se blocheaza scriptul, in oricare din situatiile de mai sus, tu nu esti blocat permanent fiindca cu o pauza sau/si un restart totul se rezolva doar ca trebuie sa stii cand este situatia fiindca nu poti da pauza si restart dupa fiecare request. Cum as putea sa rezolv aceste probleme? Multumesc mult de tot! Quote
UnixDevel Posted September 12, 2021 Report Posted September 12, 2021 (edited) cel mai bine ai face ca pentru fiecare request sa fie bagat intr-un queue . si cu status in cazul in care unul din queue moare sa il trimiti la un failed jobs. sincer chestia asta merge pe laravel super usor cu supervisor si jobs. pe python nu stiu ceva care sa te puna in directia buna . Efectiv iti trebuie un stack si sa stii pozitia la care a ramas ultima oara. Edited September 12, 2021 by lzomedia Quote
Che Posted September 12, 2021 Author Report Posted September 12, 2021 Ar fi frumos daca modulul yfinance din python sa aiba timed_out ca si parametru cand vrei sa faci call la o informatie anume ca astfel ii poti face catch cu un try si catch si in caz de timed_out faci pass si continue si ai rezolvat problema. Chestia este ca nu stiu daca are asa ceva sau cum ai putea face asa ceva. Va rog, daca stiti sa postati un link ca eu m-am uitat pe github si nu am gasit dar eu nu sunt asa de experminentat in programare si poate totusi este pe undeva si nu l-am vazut sau poate se poate face pur si simplu insa nu stiu cum fiindca ar trebui sa fac catch exact la eroare doar ca nu stiu care anume este eroarea si cum ar suna ea fiindca nu a afisat niciodata nimic in situatiile enumerate in primul post de la inceputul acestui topic. Prin urmare, daca nu afiseaza nimic (sau poate afiseaza si nu stiu eu) inseamna ca nici nu poti face catch de novo pe eroare, asa ma gandesc, nu stiu. In alta ordine de idei, m-am gandit sa fac un loop cu terminare break atunci cand dureaza prea mult. Mai exact, codul meu nu este cu while true ci este asa: 1. o bucla for care ia dintr-o lista de tickere pe fiecare ticker si face call cu yfinance. 2. pentru fiecare ticker din lista se face un try si catch cu exceptii care deja prinde cateva erori care au tot aparut pana in momentul de fata, inclusiv keyboardinterrupt ca sa il pot opri din tastatura si continua cand am nevoie. Prin urmare nu prea stiu cum sa fac un while true cu break in functie de timpul scurs din moemnt ce eu am for each_ticker in list_tikers: try: yfinance.get_info(each_ticker) catch eroare_name1: pass catch eroare_name1: do_something etc. Prin urmare unde bag while true cu break asa cum am gasit aici? https://stackoverflow.com/questions/13293269/how-would-i-stop-a-while-loop-after-n-amount-of-time Alta metoda ar fi sa fac catch exact la fiecare eroare doar ca nu stiu care sunt erorile din moment ce eu doar am vazut rezultatul si nu mi-a afisat nici un text de eroare. Multumesc mult de tot! Quote
gigiRoman Posted September 12, 2021 Report Posted September 12, 2021 Pai fa tu try catch si cand iti da timeout intra pe catch. Daca nu e in librarie e clar ca tratarea erorilor iti este lasara tie. Quote
Che Posted September 12, 2021 Author Report Posted September 12, 2021 1 hour ago, gigiRoman said: Pai fa tu try catch si cand iti da timeout intra pe catch. Pai tocmai asta este ca eu l-am facut cu try si catch de la bun inceput si unele catch sunt cu prinderea erorilor specifice dar am lasat la final si un catch e: print(e.text) #sau ceva de genul care sa fie la modul general, adica sa prinda orice alta eroare si sa o afiseze, prin urmare inclusiv asta, exact asa cum zici tu. Doar ca nu se intampla asa. Nu s-a intamplat niciodata sa afiseze vreo eroare anume doar ramanea blocat si atat: On 9/11/2021 at 12:34 PM, Che said: Daca nu pica curentul ci internetul atunci ori imi scrie niste fisiere goale in loc sa fie cu informatii. Cum pot rezolva asta din moment ce unele companii chiar nu au informatii dar cand se intampla asta scrie un fisier gol si la cele care au info? Tot la fel, poate sa pice internetul si in loc de fisiere goale se blocheaza la accesarea informatiilor curente si practic sta asa la nesfarsit chiar daca internetul si-a revenit el pur si simplu arata "retrieveing..." si ramane asa blocat. Cum se poate rezolva asta? O alta chestie este atunci cand de la prea multe requesturi (sau server maintenance - nu pot sti exact de la ce) se intampla exact ca mai sus adica ramane blocat. Cum fac sa rezolv asta? Quote
yoyois Posted September 12, 2021 Report Posted September 12, 2021 15 minutes ago, Che said: Pai tocmai asta este ca eu l-am facut cu try si catch de la bun inceput si unele catch sunt cu prinderea erorilor specifice dar am lasat la final si un catch e: print(e.text) #sau ceva de genul care sa fie la modul general, adica sa prinda orice alta eroare si sa o afiseze, prin urmare inclusiv asta, exact asa cum zici tu. Doar ca nu se intampla asa. Nu s-a intamplat niciodata sa afiseze vreo eroare anume doar ramanea blocat si atat: Daca tu vrei atata automatie trebuie sa si o programezi. Ce zice gigi e sa faci un watchdog. Un program/librarie/thread care monitorizeaza cat timp dureaza un request. Si daca dureaza mai mult de x secunde ii da skip. Egal un watchdog poate sa dea ping la google.com din X in X secunde. Daca pingul nu merge inseamna ca ti-a cazut netul. Deci watchdogul opreste toata procesarea pana cand pingul reuseste. Google "watchdog". Ce vrei tu e un watchdog custom care sa monitorizeze toate conditiile de mediu si sa asigure functionarea scriptului tau principal. Sunt multe ideei care par plauzibile. -timeout daca un request ia mai mult de 5s -ping la google in fiecare secunda (verifici conexiunea) - paginile care au esuat sunt re-verificate la final, dupa ce a trecut putin timp. - se pot face mai multe requesturi in paralel(async) pentru a mari viteza - sanity check pe response (sa nu salvezi mii de pagini de erori/garbage) - caching la Disk IO ca sa salvezi viata hddului si viteza de procesare - etc. 1 1 Quote
Active Members MrGrj Posted September 13, 2021 Active Members Report Posted September 13, 2021 E destul de usor ce vrei tu sa faci si poti combina solutiile de mai sus. Intr-adevar, pentru a fi sigur ca scriptul isi reia treaba de unde a ramas iti trebuie un Queuing mechanism in care sa stochezi statusul si id-ul fiecarui request in parte. Iti va fi usor sa reiei taskurile de unde au ramas. Ca sa rezolvi problemele cu no internet connection, curent nema, apocalipsa etc e ceva mai interesant (intra cumva in categoria de disaster recovery - multa teorie). Dar pe scurt, cu cateva try / except-uri ar trebui sa o rezolvi (e.g. poti face initial un HEAD request catre yfinance + retry de cateva ori in cazul in care requestul faileaza. Daca dupa cateva retry-uri nu primesti nimic de la url-ul respectiv, treci la urmatorul si pui in queue url-ul precedent pentru a-l incerca mai tarziu bla bla e mult de scris). Poti incerca urmatorul stack: - Python (il folosesti deja) - RabbitMQ (message broker) - Ceva DB (ceva cum ar fi Mongo cred ca ar merge perfect din moment ce nu pare ca ai vreo relatie intre datele de care ai nevoie) Ideea generala pentru a scapa de acel "retrieving..." e ca trebuie sa faci mereu sanity request check-uri care sa te asigure ca urmatoarele reqs vor merge. In caz contrar, tratezi acolo ce e de tratat. E.g: try: import httplib except: import http.client as httplib def i_have_internet(): conn = httplib.HTTPConnection("www.google.com", timeout=5) try: conn.request("HEAD", "/") conn.close() return True except: conn.close() return False def main(): if i_have_internet(): # do your stuff (process yfinance bla bla) else: # wait, retry, check internet settings or w/e u want main() Mai sus e un exemplu simplu de check insa tu ar trebui sa tratezi tot ce ai nevoie. Asta se rezolva pe parcurs dupa ce intampini toate problemele. 1 2 Quote
Che Posted September 13, 2021 Author Report Posted September 13, 2021 @MrGrj Cum faci atunci cand conexiunea ramane blocata? Adica internet este, ping catre google este dar conexiunea yfinance ramane blocat pur si simplu fara sa arate vreo eroare, fara nimic, doar astepti sa ia rezultatele si astepti si tot astepti dar nu se mai intampla nimic fiindca conexiunea este cumva inghetata. Am observat ca se intampla asta cand lasam scriptul sa ruleze dar pe PC deschideam IEInspector HTTP Analyzor ca sa faca sniff sa vad ce headere si ce parametri foloseste scriptul si pur si simplu ramanea blocat fara sa fac absolut nimic si fara sa-i dau kill la script sau sa il analizez in program, asa pur si simplu. Tot la fel se mai intampla uneori asa pur si simplu, fara sa fac nimic, cred ca de la prea multe accesari, nu simultane sau ceva dar pur si simplu cred ca te ia la ochi dupa 100+ de accesari pe acelasi link, nu stiu sigur, banuiesc. Si tot la fel, nici un mesaj de eroare, nimic, doar ramanea blocat si nu se mai intampla nimic. Cum pot face catch sau manageria situatia asta? Ma poti ajuta, te rog mult? Multumesc mult de tot! Quote
Active Members MrGrj Posted September 13, 2021 Active Members Report Posted September 13, 2021 (edited) 58 minutes ago, Che said: Cum faci atunci cand conexiunea ramane blocata? Adica internet este, ping catre google este dar conexiunea yfinance ramane blocat pur si simplu fara sa arate vreo eroare, fara nimic, doar astepti sa ia rezultatele si astepti si tot astepti dar nu se mai intampla nimic fiindca conexiunea este cumva inghetata. Setezi `timeout=<cat_vrei_tu>` pe fiecare request (e.g. `requests.get(url, timeout=10)`), dai retry de 3 ori sau cat vrei si treci mai departe daca resursa respectiva e busita (eventual stochezi in logs ca sa vezi ce se intampla si de ce nu merge). De asemenea, e posibil sa ai ceva antibots mechanism si sa iti dea block pentru cateva secunde/minute/ani etc...caz in care tre' sa folosesti proxies / socks. Uneori merge doar daca pui un mic sleep intre requesturi (e posibil sa le omori serveru') + schimbi User-Agent. Edited September 13, 2021 by MrGrj Quote
Che Posted September 13, 2021 Author Report Posted September 13, 2021 1 hour ago, MrGrj said: Setezi `timeout=<cat_vrei_tu>` pe fiecare request (e.g. `requests.get(url, timeout=10)`), dai retry de 3 ori sau cat vrei si treci mai departe daca resursa respectiva e busita (eventual stochezi in logs ca sa vezi ce se intampla si de ce nu merge). De asemenea, e posibil sa ai ceva antibots mechanism si sa iti dea block pentru cateva secunde/minute/ani etc...caz in care tre' sa folosesti proxies / socks. Uneori merge doar daca pui un mic sleep intre requesturi (e posibil sa le omori serveru') + schimbi User-Agent. Exact asa m-am gandit si eu la inceput doar ca yfinance nu are ca si parametru timeout. Este o metoda, nici macar o functie. https://pypi.org/project/yfinance/ ex. import yfinance as yf msft = yf.Ticker("MSFT") # get stock info msft.info Practic ii faci try si catch pe msft.info pe care il salvezi in linia de cod urmatoare daca nu a intervenit nici o eroare. Ai putea, te rog, sa-mi arati cum se poate face timeout si catch in caz de timeout (banuiesc ca trebuie) la asa ceva? Multumesc mult de tot! Quote
SirGod Posted September 13, 2021 Report Posted September 13, 2021 5 minutes ago, Che said: Exact asa m-am gandit si eu la inceput doar ca yfinance nu are ca si parametru timeout. Este o metoda, nici macar o functie. https://pypi.org/project/yfinance/ ex. import yfinance as yf msft = yf.Ticker("MSFT") # get stock info msft.info Practic ii faci try si catch pe msft.info pe care il salvezi in linia de cod urmatoare daca nu a intervenit nici o eroare. Ai putea, te rog, sa-mi arati cum se poate face timeout si catch in caz de timeout (banuiesc ca trebuie) la asa ceva? Multumesc mult de tot! La prima vedere pare destul de simpla biblioteca, cel mai sigur o modifici si adaugi tu parametrul de timeout. 1 Quote
Active Members MrGrj Posted September 13, 2021 Active Members Report Posted September 13, 2021 (edited) M-am uitat la ei pe lib si nu suporta timeout ca parametru. Ca workaround poti face ceva de genu': import requests import yfinance as yf import functools session = requests.Session() session.request = functools.partial(session.request, timeout=30) # replace requests library in yfinance yf.base._requests = session yf.utils._requests = session yf.ticker._requests = session The above should do the trick Edited September 13, 2021 by MrGrj 1 1 Quote
Che Posted September 13, 2021 Author Report Posted September 13, 2021 @MrGrj Multumesc mult de tot! O singura nelamurire mai am: Va trebui sa fac un try si catch si acum stiu ca are ca si timeout prestabilit 30 de secunde. Intrebarea este cum anume fac catch pe timeout? De exemplu cand apesi CTRL+C de la tastatura ca sa opresti scriptul tu poti sa-i faci catch pe KeyboardInterrupt astfel: try: main() except KeyboardInterrupt: print('Interrupted') Ce anume pui la catch (except) in caz de timeout? Multumesc mult de tot! Quote
Active Members MrGrj Posted September 13, 2021 Active Members Report Posted September 13, 2021 12 minutes ago, Che said: ntrebarea este cum anume fac catch pe timeout? Here u go: try: # make the request here except requests.Timeout as timeout_err: # handle timeout print(timeout_err) except requests.RequestException as req_err: # handle other errors print(req_err) 1 Quote
Che Posted October 1, 2021 Author Report Posted October 1, 2021 Acesta este scriptul dat ca exemplu de ei ca sa inteleaga fiecare cum se foloseste libraria yfinance: import yfinance as yf msft = yf.Ticker("MSFT") # get stock info msft.info # get historical market data hist = msft.history(period="max") # show actions (dividends, splits) msft.actions # show dividends msft.dividends # show splits msft.splits # show financials msft.financials msft.quarterly_financials # show major holders msft.major_holders # show institutional holders msft.institutional_holders # show balance sheet msft.balance_sheet msft.quarterly_balance_sheet # show cashflow msft.cashflow msft.quarterly_cashflow # show earnings msft.earnings msft.quarterly_earnings # show sustainability msft.sustainability # show analysts recommendations msft.recommendations # show next event (earnings, etc) msft.calendar # show ISIN code - *experimental* # ISIN = International Securities Identification Number msft.isin # show options expirations msft.options # get option chain for specific expiration opt = msft.option_chain('YYYY-MM-DD') # data available via: opt.calls, opt.puts Faza este ca eu in momentul de fata trebuie sa iau pe rand fiecare metoda si sa stau cam 7-10 zile pana termina de facut request-urile pentru fiecare metoda in parte, adica trebuie sa iau msft.info si sa stau 10 zile sa astept pana descarca informatiile pentru fiecare ticker in parte (nu doar msft cum e dat in exemplu ci ticker.info si apoi salvat si tot asa pentru fiecare ticker cate un request ca sa ia info pentru acel ticker si in total sunt 52.000 de tickere si dureaza cam 7 sau chiar 10 zile pentru fiecare. Problema este ca dureaza prea mult pentru fiecare metoda in parte sa astepti cate 10 zile ca pana termin eu sa le descarc deja unele informatii s-au schimbat si trebuie sa le descarc din nou ca deja la .info acum la unele dintre ele difere fata de ce am descarcat eu initial si acum trebuie sa o iau de la capat si la .info nu te-ai astepta sa apara schimbari, nu mai zic de history si recommendations. Nu se poate cumva ca printr-un singur request sa accesez toate metodele de mai sus (.info, .history, .splits, .dividends etc.) si sa le salvez pe fiecare in parte in fisiere fara ca sa fac cate un request pentru fiecare metoda in parte si pentru fiecare ticker in parte? @MrGrj Te rog mult, mult, mult de tot! Multumesc din suflet! Quote