Seite 7 von 9
Re: Dateien herunterladen und in einem Verzeichnis ablegen
Verfasst: Mittwoch 5. April 2017, 15:54
von __deets__
Du erzeugst einen Log-File-Namen, und gibst den zurueck. Das hast du schon (generate_logfile).
Du speicherst dir den Namen in einer Variablen, und den gibst du weiter an all die anderen Dinge, die ihn brauchen:
Code: Alles auswählen
def generate_logfile():
...
def ensure_logdir_exists(logfilename):
....
def initialize_logger():
logfile_name = generate_logfile()
ensure_logdir_exists(logfile_name)
...
Re: Dateien herunterladen und in einem Verzeichnis ablegen
Verfasst: Mittwoch 5. April 2017, 15:56
von Sirius3
@aaron: jetzt hast Du wieder den funktionierenden Zustand gezeigt. Und vom funktionierenden zum kaputten Zustand hast Du mehr geändert, als eigentlich nötig wäre. Die Frage ist, warum hast Du das gemacht? Irgendetwas hast Du Dir ja dabei gedacht. Um Dir helfen zu können, wäre es gut, was Du Dir dabei gedacht hast, weil wie es generell richtig ist, hat __deets__ ja schon geschrieben.
Re: Dateien herunterladen und in einem Verzeichnis ablegen
Verfasst: Mittwoch 5. April 2017, 17:59
von aaron
Der Code sieht jetzt so aus. Es funktioniert die Funktion def ensure_logdir_exits(logfilename): nocht nicht. Mir ist nicht klar, wie die Argumentübergabe an die Funktion def ensure_logdir_exits(logfilename): erfolgt.
Code: Alles auswählen
def generate_logfile():
return os.path.join("log", str(datetime.date.today())+'.log')
def ensure_logdir_exits(logfilename):
if not os.path.exists(os.path.dirname(logfilename)):
os.makedirs(os.path.dirname(logfilename))
def initialize_logger():
logfile_name = generate_logfile()
print(logfile_name)
ensure_logdir_exists(logfile_name)
logger = logging.getLogger('Data download')
logger.setLevel(logging.DEBUG)
handler = logging.FileHandler(logfile_name)
handler.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
# 'application' code
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')
Re: Dateien herunterladen und in einem Verzeichnis ablegen
Verfasst: Mittwoch 5. April 2017, 18:28
von Sirius3
@aaron: wenn Du eine Fehlermeldung erhältst, sagt sie Dir, was Du falsch machst.
Re: Dateien herunterladen und in einem Verzeichnis ablegen
Verfasst: Mittwoch 5. April 2017, 18:34
von aaron
Sorry die Fehlermeldung:
Code: Alles auswählen
Traceback (most recent call last):
File "TickDataCsv.py", line 115, in <module>
main()
File "TickDataCsv.py", line 108, in main
initialize_logger()
File "TickDataCsv.py", line 22, in initialize_logger
ensure_logdir_exists(logfile_name)
NameError: global name 'ensure_logdir_exists' is not defined
Re: Dateien herunterladen und in einem Verzeichnis ablegen
Verfasst: Mittwoch 5. April 2017, 18:41
von pillmuncher
Vergleich mal:
Code: Alles auswählen
def ensure_logdir_exits(logfilename):
... ^^^
def initialize_logger():
...
ensure_logdir_exists(logfile_name)
... ^^^
Code: Alles auswählen
Traceback (most recent call last):
...
NameError: global name 'ensure_logdir_exists' is not defined
^^^
Re: Dateien herunterladen und in einem Verzeichnis ablegen
Verfasst: Mittwoch 5. April 2017, 18:47
von aaron
DANKE
Re: Dateien herunterladen und in einem Verzeichnis ablegen
Verfasst: Mittwoch 5. April 2017, 19:04
von Sirius3
@aaron: die Fehlermeldung sollte Dir eigentlich gleich sagen, dass Du Dich irgendwo vertippt hast, ohne dass Du hier extra fragen mußt. Programmieren heißt nicht, zu hoffen, dass irgendwer für jemanden die Arbeit macht.
Re: Dateien herunterladen und in einem Verzeichnis ablegen
Verfasst: Sonntag 9. April 2017, 09:55
von aaron
Ich versuche das exception handling zu implementieren. Es kann zu 3 Fehlertypen
kommen.
1. Die Datei ist auf dem Server nicht vorhanden, obwohl diese eigentlich da
sein sollte oder das Datum liegt in der Zukunft.
HTTP Error 404: Not Found
2. Die Datei ist Beschädigt.
CRC check failed 0x64e41a56 != 0x966a8aabL
3. Die Datei ist auf dem Server vorhanden und wird heruntergeladen. Beim Öffnen
der Datei wird festgestellt, das diese bis auf die Tabellenüberschrift leer
ist. Die Größe der Datei beträgt nur 52 Bytes.
Meine Fragen sind:
Angenommen, eine Datei ist auf dem Server nicht vorhanden. Wie geht es weiter,
damit die nächste Datei heruntergeladen und das Programm nicht beendet wird?
Als letzten Schritt möchte ich diese Informationen in das logfile schreiben.
Hier ein Versuch ein Teil des exception handling einzubauen.
Code: Alles auswählen
def pull_file(symbol, year, week):
try:
url = URL_TEMPLATE.format(symbol, year, week)
response = urllib2.urlopen(url)
return response.read()
except urllib2.HTTPError as e:
print(e)
exit(1)
def print_data_length(data):
try:
f = gzip.GzipFile(fileobj=StringIO(data))
length = 0
while True:
block = f.read(1024*1024)
if not block:
break
length += len(block)
print(length)
except IOError as e:
print(e)
exit(1)
Re: Dateien herunterladen und in einem Verzeichnis ablegen
Verfasst: Sonntag 9. April 2017, 12:11
von Sirius3
@aaron: Sinn der Fehlerbehandlung ist es ja das Programm wieder in einen Zustand zu versetzen, dass es weiterlaufen kann. Ein ›exit‹ macht dagegen das Gegenteil. So kann man die Fehlerbehandlung gleich weglassen. An welcher Stelle im Programm macht es denn einen Unterschied, ob etwas erfolgreich war, oder nicht?
Re: Dateien herunterladen und in einem Verzeichnis ablegen
Verfasst: Sonntag 9. April 2017, 14:24
von aaron
Zu Deiner Frage.
An welcher Stelle im Programm macht es denn einen Unterschied, ob etwas erfolgreich war, oder nicht?
Ich denke es beginnt schon mit dem Erstellen des Dateinamens.
Code: Alles auswählen
def generate_filename(symbol, year, week):
return os.path.join("data", symbol, str(year), '{}.csv.gz'.format(week))
Ist die Datei auf dem Server nicht vorhanden oder defekt, dann kann der Dateiname für die nächste Datei erstellt werden.
Das Traceback zeigt aber einen Fehler in der Funktion pulled file.
Code: Alles auswählen
Traceback (most recent call last):
File "TickDataCsv.py", line 115, in <module>
main()
File "TickDataCsv.py", line 110, in main
fetch_whole_year(symbol, 2017)
File "TickDataCsv.py", line 83, in fetch_whole_year
data = pull_file(symbol, year, week)
File "TickDataCsv.py", line 46, in pull_file
response = urllib2.urlopen(url)
File "/usr/lib64/python2.7/urllib2.py", line 154, in urlopen
return opener.open(url, data, timeout)
File "/usr/lib64/python2.7/urllib2.py", line 437, in open
response = meth(req, response)
File "/usr/lib64/python2.7/urllib2.py", line 550, in http_response
'http', request, response, code, msg, hdrs)
File "/usr/lib64/python2.7/urllib2.py", line 475, in error
return self._call_chain(*args)
File "/usr/lib64/python2.7/urllib2.py", line 409, in _call_chain
result = func(*args)
File "/usr/lib64/python2.7/urllib2.py", line 558, in http_error_default
raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)
urllib2.HTTPError: HTTP Error 404: Not Found
Code: Alles auswählen
def pull_file(symbol, year, week):
url = URL_TEMPLATE.format(symbol, year, week)
response = urllib2.urlopen(url)
return response.read()
Re: Dateien herunterladen und in einem Verzeichnis ablegen
Verfasst: Sonntag 9. April 2017, 17:30
von Sirius3
@aaron: der entscheidende Satz, den Du geschrieben hast, ist folgender:
aaron hat geschrieben:Ist die Datei auf dem Server nicht vorhanden oder defekt, dann kann der Dateiname für die nächste Datei erstellt werden.
Das Traceback zeigt aber einen Fehler in der Funktion pulled file.
Kannst Du in generate_filename mit der nächsten Datei weitermachen? Nein, weil da ja gar kein Fehler auftreten kann. Kannst Du in pull_file mit der nächsten Datei weitermachen? Nein! Weil die Funktion ja nur für eine Datei gedacht ist.
Was ist dann die Lösung? Dort, wo Du in der Schleife alle Dateien durchgehst, hast Du die Möglichkeit, bei einem Fehler einfach mit der nächsten Datei weiterzumachen. Dort wäre also der richtige Platz für eine Fehlerbehandlung.
Re: Dateien herunterladen und in einem Verzeichnis ablegen
Verfasst: Sonntag 9. April 2017, 18:53
von aaron
Hier die veränderte Funktion fetch_whole_year. Richtigerweise wird CRC check failed 0x64e41a56 != 0x966a8aabL bei der beschädigten Datei ausgegeben. Dannach stopt das Programm. Wie laße ich die funktion weiter laufen?
Code: Alles auswählen
def fetch_whole_year(symbol, year):
try:
for symbol in symbol:
last_week = datetime.date(year, 12, 31).isocalendar()[1]
for week in range(1, last_week + 1):
if not exists_file(symbol, year, week):
data = pull_file(symbol, year, week)
print_data_length(data)
save_file(symbol, year, week, data)
else:
print("File for {}/{}/{} already fetched.".format(symbol,»
except IOError as e:
print(e)
Re: Dateien herunterladen und in einem Verzeichnis ablegen
Verfasst: Sonntag 9. April 2017, 20:07
von Sirius3
@aaron: warum brichst Du auch die ganze Schleife ab, wenn bei einem Datum ein Fehler auftritt?
Re: Dateien herunterladen und in einem Verzeichnis ablegen
Verfasst: Sonntag 9. April 2017, 21:00
von aaron
So sieht die Funktion jetzt aus. Das scheint jetzt soweit zu funktionieren. Für die Wochen ab Kalenderwoche 13 2017 gibt die Funktion jetzt 39 mal HTTP Error 404: Not Found aus, was richtig ist. Die Schleife hört erst nach der Kalenderwoche 52 auf zu laufen. Wiie gehe ich jetzt vor um zu prüfen ob die Kalenderwoche in der Zukunft liegt? Noch eine Schleife die die aktuelle Kalenderwoche abfragt?
Code: Alles auswählen
def fetch_whole_year(symbol, year):
for symbol in symbol:
last_week = datetime.date(year, 12, 31).isocalendar()[1]
for week in range(1, last_week + 1):
try:
if not exists_file(symbol, year, week):
data = pull_file(symbol, year, week)
print_data_length(data)
save_file(symbol, year, week, data)
except IOError as e:
print(e)
else:
print("File for {}/{}/{} already fetched.".format(
symbol, year, week)
)
Re: Dateien herunterladen und in einem Verzeichnis ablegen
Verfasst: Montag 10. April 2017, 14:26
von aaron
Ich wollte das Print aus der Funktion in ein Logfile umleiten. Leider scheint diese Idee falsch zu sein. Ich wollte innerhalb der Funktion das Logging mit logger = initialize_logger() aufrufen. Bitte erklärt mir doch was ich falsch gemacht habe.
Code: Alles auswählen
def fetch_whole_year(symbol, year):
logger = initialize_logger()
for symbol in symbol:
last_week = datetime.date(year, 12, 31).isocalendar()[1]
for week in range(1, last_week + 1):
try:
if not exists_file(symbol, year, week):
data = pull_file(symbol, year, week)
print_data_length(data)
save_file(symbol, year, week, data)
except IOError as e:
print(e)
logger.error(e)
else:
print("File for {}/{}/{} already fetched.".format(
symbol, year, week)
)
logger.info("File for {}/{}/{} already fetched.".format(
symbol, year, week)
)
Re: Dateien herunterladen und in einem Verzeichnis ablegen
Verfasst: Mittwoch 12. April 2017, 07:17
von aaron
Ich habe drei Funktionen, die noch nicht wie gewünscht funktionieren. Bei der Funktion fetch_whole_year ist das Logging nicht richtig implementiert.
In meinen Post davor habe ich meine Idee gezeigt. Hier noch einmal die Funktion ohne das Logging.
Frage: Wie wird das Logging richtig einhebaut? In dieser Funktion soll dann auch die nächste Funktion initialize_logger aufgerufen werden. Wie rufe ich die zweite Funktion initialize_logger in der Funktion fetch_whole_year auf? Sollte die Funktion initilise_logger auch durch diese Funktion aufgerufen werden? Das Absenden der Email sollte dann abschliessend durch die Funktion initialise_logger erfolgen. Nachdem das Logfile geschrieben wurde soll dieses per Email verschickt werden. Ich habe eine Funktion send_email geschrieben. Hier sind noch zwei Fehler zu beheben.
1. Hier rufe ich die Funktion generate_logfile auf. Wie ich aber gelernt habe sollte die Fuktion generate_logfile nicht mehrfach aufgerufen werden. Welche Idee ist richtig?
2. Fehler beim Versenden der Email. Ich bekomme folgende Fehlermeldung:
Code: Alles auswählen
def fetch_whole_year(symbol, year):
for symbol in symbol:
last_week = datetime.date(year, 12, 31).isocalendar()[1]
for week in range(1, last_week + 1):
try:
if not exists_file(symbol, year, week):
data = pull_file(symbol, year, week)
print_data_length(data)
save_file(symbol, year, week, data)
except IOError as e:
print(e)
else:
print("File for {}/{}/{} already fetched.".format(
symbol, year, week)
)
def initialize_logger():
logfile_name = generate_logfile()
print(logfile_name)
ensure_logdir_exists(logfile_name)
logger = logging.getLogger('Data download')
logger.setLevel(logging.DEBUG)
handler = logging.FileHandler(logfile_name)
handler.setLevel(logging.DEBUG)
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
handler.setFormatter(formatter)
logger.addHandler(handler)
# application' code
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')
Code: Alles auswählen
def send_email():
email_user = 'user'
email_pwd = 'passwd'
SENDER = 'absender@example.com'
RECIPIENT = 'empfenger@example.com'
logfile = generate_logfile()
fp = open(logfile, 'rb')
msg = MIMEText(fp.read())
fp.close()
msg['From'] = SENDER
msg['To'] = RECIPIENT
msg['Subject'] = 'The logfile from %s' % logfile
try:
server = smtplib.SMTP('wpxxxxxx.mailout.server-he.de', '25')
server.set_debuglevel(True)
server.ehlo()
server.starttls()
server.login(email_user, email_pwd)
server.sendmail(SENDER, [RECIPIENT], msg.as_string())
server.close()
print 'Email send successfully.'
except:
print "Failed to send the email."
Code: Alles auswählen
reply: '354 Enter message, ending with "." on a line by itself\r\n'
reply: retcode (354); Msg: Enter message, ending with "." on a line by itself
data: (354, 'Enter message, ending with "." on a line by itself')
Re: Dateien herunterladen und in einem Verzeichnis ablegen
Verfasst: Mittwoch 12. April 2017, 08:43
von Sirius3
@aaron: Du verwendest Logger falsch. Wenn Du logging verwendest, dann brauchst Du nicht auch noch alles per print auszugeben, weil das ja durch eine passende Logger-Konfiguration passieren kann. Innerhalb einer Funktion sollte gar kein spezieller Logger initialisiert werden. Das passiert am Anfang des Hauptprogramms, wo man die Konfiguration auch per Konfigurationsdatei erledigen kann, so dass man bei geänderten Anforderungen ans Logging das Programm gar nicht anfassen muß. Sodann hat normalerweise jedes Modul einen modulweiten logger. Die Log-Meldungen sind falsch. Für Exceptions gibt es logger.exception, das auch den Stacktrace mitloggt. Für erfolgreiche Downloads wird immer "already fetched" ausgegeben, was ja nicht stimmt, wenn die Datei eben noch nicht existiert hat.
Zur Email: Du merkst gar nicht, was falsch läuft, weil Du jede Exception mit einer nichtssagenden Ausgabe unterdrückst. So funktioniert Exception-Handling nicht, wie wir schon mehrfach betont haben. Die Ausgabe kommt daher, dass Du debuglevel auf True gesetzt hast, sind also kein Zeichen für einen Fehler.
Re: Dateien herunterladen und in einem Verzeichnis ablegen
Verfasst: Mittwoch 12. April 2017, 13:40
von aaron
Ich bekomme bei der Ansicht der Emailquelldaten folgenden Fehler gemeldet.
X-ACL-Warn: Message does not conform to RFC2822 standard und die Email landet immer im Spammordner
Re: Dateien herunterladen und in einem Verzeichnis ablegen
Verfasst: Mittwoch 12. April 2017, 15:43
von Sirius3
@aaron: dann solltest Du schauen ob msg.as_string() RFC2822-konform ist (wovon ich mal ausgehe) oder ob Dein Mail-Gateway inkompatibel ist.