Dateien herunterladen und in einem Verzeichnis ablegen

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.
aaron
User
Beiträge: 92
Registriert: Donnerstag 1. Dezember 2016, 23:10

Fehler im Mail-gateway gefunden. Jetzt landet die Email im Posteingangsordner. Danke
aaron
User
Beiträge: 92
Registriert: Donnerstag 1. Dezember 2016, 23:10

Ich bin immer noch beim Logging. Leider verstehe ich die Details nicht, obwohl ich schon Stunden lese und google bemühe. Bitte erklärt doch einem Erstklässler wie ich das Logging in meinen Programm richtig zum Laufen bringe. Ich bekomme immer nur die Meldungen aus den Zeilen unterhalb von # application code und nicht die Meldung aus der Funktion fetch_whole_year. In dem Logfile sollen auch die Informationen über den erfolgreichen Download der anderen Dateien. Nicht nur die defekten, oder nicht vorhandenen Dateien.

Code: Alles auswählen

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 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 Exception as e:                                            
                  logging.exception(e)                                          
              else:                                                             
                  print("File for {}/{}/{} already fetched.".format(            
                      symbol, year, week)                                       
                  )              

Code: Alles auswählen

Traceback (most recent call last):
  File "TickDataCsv.py", line 103, in fetch_whole_year
    data = pull_file(symbol, year, week)
  File "TickDataCsv.py", line 55, 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)
HTTPError: HTTP Error 404: Not Found
ERROR:root:HTTP Error 404: Not Found
Sirius3
User
Beiträge: 17757
Registriert: Sonntag 21. Oktober 2012, 17:20

@aaron: print ≠ logging
aaron
User
Beiträge: 92
Registriert: Donnerstag 1. Dezember 2016, 23:10

Danke für die Antwort. Das habe ich mittlerweile auch herausgefunden. Ich brauche ein Beispielprogramm bei dem ich einmal sehe, wie das Logging richtig eingesetzt wird. Das heißt ich erstelle die Lognachrichten selbst?
Benutzeravatar
Kebap
User
Beiträge: 687
Registriert: Dienstag 15. November 2011, 14:20
Wohnort: Dortmund

aaron hat geschrieben:Ich brauche ein Beispielprogramm bei dem ich einmal sehe, wie das Logging richtig eingesetzt wird.
Sicherlich hast du dir schon die offizielle Dokumentation zu Logging samt Beispielen angeschaut, bevor du hier Grundsätzliches erfragst?

https://docs.python.org/3.6/howto/logging.html
MorgenGrauen: 1 Welt, 8 Rassen, 13 Gilden, >250 Abenteuer, >5000 Waffen & Rüstungen,
>7000 NPC, >16000 Räume, >200 freiwillige Programmierer, nur Text, viel Spaß, seit 1992.
aaron
User
Beiträge: 92
Registriert: Donnerstag 1. Dezember 2016, 23:10

Ich beschäftige mich immer noch mit dem Logging in meinem Programm. Ich möchte euch bitten mir die fehlenden Zeilen Code einmal zu schreiben. Ich verbringe mit diesem Teil des Programmes schon viele Tage. Ich finde kein Beispiel. Auch die Dokumentation hilft mir nicht, weil ich nicht weiß, wie das Logging richtig eingebaut wird.

Code: Alles auswählen

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 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 Exception as e:                                               
                  logging.exception(e)                                             
              else:                                                                
                  print("File for {}/{}/{} already fetched.".format(               
                      symbol, year, week)                                          
                  )          
Aufgerufen wird das Logging in der Funktion main()

Code: Alles auswählen

def main():                                                                      
      initialize_logger()     
Sirius3
User
Beiträge: 17757
Registriert: Sonntag 21. Oktober 2012, 17:20

@aaron: was ist denn nun Dein Problem? Was möchtest Du mit Logging erreichen, was hast Du im Moment. Wie weicht das Ergebnis, das Du hast von dem ab, das Du willst?
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Was funktioniert denn nicht? Fuer mich geht dein code (nachdem ich etwas drumrum gebaut habe was du nicht zeigst)

Code: Alles auswählen

import os
import logging

def generate_logfile():
    return "/tmp/test-foo/logfile.log"

def ensure_logdir_exists(logfile_name):
      dir = os.path.dirname(logfile_name)
      if not os.path.exists(dir):
            os.makedirs(dir)


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')


def main():
    initialize_logger()


if __name__ == '__main__':
     main()
Bekomme ich eine Datei mit Eintraegen, so wie erwartet.

In deiner fetch_whole_year Funktion rufst du kein logging auf, nur so am Rande. Insofern kann da dann auch nichts geloggt werden.
aaron
User
Beiträge: 92
Registriert: Donnerstag 1. Dezember 2016, 23:10

Danke für die Antworten. Das ist ja genau meine Frage, wie rufe ich das Logging in der Funktion fetch_whole-year auf? Hier noch einmal die Funktionen, die genau das machen was sie sollen. Das Ergebnis ist ein Logfile mit folgendem Inhalt. Ich möchte, dass die Fehlermeldungen, wie die Datei ist auf dem Server nicht vorhanden, oder die Datei ist beschädigt.

Code: Alles auswählen

2017-04-26 15:39:35,141 - Data download - DEBUG - debug message
2017-04-26 15:39:35,141 - Data download - INFO - info message
2017-04-26 15:39:35,141 - Data download - WARNING - warn message
2017-04-26 15:39:35,141 - Data download - ERROR - error message
2017-04-26 15:39:35,141 - Data download - CRITICAL - critical message

Code: Alles auswählen

def generate_logfile():                                                          
      return os.path.join("log", str(datetime.date.today())+'.log')                
                                                                                   
                                                                                   
  def ensure_logdir_exists(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'
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Der Trick ist das getLogger mit dem gleichen Namen immer den gleichen Logger zurueckgibt. Der ist an anderer Stelle (also initialize_logger) konfiguriert worden, aber benutzen kannst du ihn ueberall mit

Code: Alles auswählen

logging.getLogger("Data download").info("text")
Ueblicherweise verwendet man stattdessen das hier https://docs.python.org/2/howto/logging ... g-tutorial beschriebene

Code: Alles auswählen

# modul-global!
logger = logging.getLogger(__name__)
Und statt in initialise_logger einen Namen anzugeben, machst du nur "logger = logging.getLogger()", womit du den root-logger bekommst. Alle anderen Logger mit Namen wie "mein.package.submodul" delegieren immer weiter nach oben, bis zur Wurzel.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Der Trick ist das getLogger mit dem gleichen Namen immer den gleichen Logger zurueckgibt. Der ist an anderer Stelle (also initialize_logger) konfiguriert worden, aber benutzen kannst du ihn ueberall mit

Code: Alles auswählen

logging.getLogger("Data download").info("text")
Ueblicherweise verwendet man stattdessen das hier https://docs.python.org/2/howto/logging ... g-tutorial beschriebene

Code: Alles auswählen

# modul-global!
logger = logging.getLogger(__name__)
Und statt in initialise_logger einen Namen anzugeben, machst du nur "logger = logging.getLogger()", womit du den root-logger bekommst. Alle anderen Logger mit Namen wie "mein.package.submodul" delegieren immer weiter nach oben, bis zur Wurzel.
aaron
User
Beiträge: 92
Registriert: Donnerstag 1. Dezember 2016, 23:10

Als Ergebnis möchte ich eine Ausgabe wie folgt haben:
File for AUDJPY/2017/1 already fetched.
File for AUDJPY/2017/2 already fetched.
File for AUDJPY/2017/3 already fetched.
File for AUDJPY/2017/4 already fetched.
File for AUDJPY/2017/5 already fetched.

Das Logging muß ja in der Schleife aufgerufen werden.
1. wenn die Datei nicht vorhanden, oder beschädigt ist.
2. wenn die Datei schon heruntergeladen wurde.
Der Inhalt des Logfiles sieht so aus:
2017-04-26 17:45:21,064 - Data download - ERROR - HTTP Error 404: Not Found
2017-04-26 17:45:21,140 - Data download - ERROR - HTTP Error 404: Not Found
2017-04-26 17:45:21,215 - Data download - ERROR - HTTP Error 404: Not Found
2017-04-26 17:45:21,300 - Data download - ERROR - HTTP Error 404: Not Found
2017-04-26 17:45:21,381 - Data download - ERROR - HTTP Error 404: Not Found
2017-04-26 17:45:21,470 - Data download - ERROR - HTTP Error 404: Not Found
2017-04-26 17:45:21,559 - Data download - ERROR - HTTP Error 404: Not Found
2017-04-26 17:45:21,636 - Data download - ERROR - HTTP Error 404: Not Found
2017-04-26 17:45:21,736 - Data download - ERROR - HTTP Error 404: Not Found
2017-04-26 17:45:21,823 - Data download - ERROR - HTTP Error 404: Not Found
2017-04-26 17:45:21,921 - Data download - ERROR - HTTP Error 404: Not Found
2017-04-26 17:45:22,006 - Data download - ERROR - HTTP Error 404: Not Found
2017-04-26 17:45:22,086 - Data download - ERROR - HTTP Error 404: Not Found
2017-04-26 17:45:22,179 - Data download - ERROR - HTTP Error 404: Not Found

ERROR - HTTP Error 404: Not Found ist ja richtig. Nur möchte ich wissen welche Datei nicht vorhanden, oder beschädigt ist.

Hier noch einmal die Funktion. So schwer kann das doch nicht sein. Das HOWTO bringt mich nicht weiter, weil ich nicht erkennen kann, wie ich was in der Schleife aufrufe.

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 Exception as e:                                               
                  logging.getLogger("Data download").error(e)                      
              else:                                                                
                  print("File for {}/{}/{} already fetched.".format(               
                      symbol, year, week)                                          
                  )    
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Na dann musst du doch nur die dazu notwendigen Daten loggen, also symbol, year, week, bzw. den Filenamen der dazugehoert.
Sirius3
User
Beiträge: 17757
Registriert: Sonntag 21. Oktober 2012, 17:20

@aaron: so

Code: Alles auswählen

import logging
logger = logging.getLogger('Data download')

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 Exception:
                logger.exception("while downloading {}/{}/{}".format(symbol, year, week))
            else:
                logger.info("File for {}/{}/{} already fetched.".format(symbol, year, week))

def initialize_logger():
    logfile_name = generate_logfile()
    ensure_logdir_exists(logfile_name)
    logging.basicConfig(filename=logfile_name, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.DEBUG)
Sirius3
User
Beiträge: 17757
Registriert: Sonntag 21. Oktober 2012, 17:20

@aaron: wenn Du am aktuellen Datum aufhören willst, dann prüf einfach auf das aktuelle Datum:

Code: Alles auswählen

last_day = min(datetime.date(year, 12, 31), datetime.date.today())
new_year, last_week, _ = day.isocalendar()
if new_year > year:
    last_week = 52
elif new_year < year:
    return
aaron
User
Beiträge: 92
Registriert: Donnerstag 1. Dezember 2016, 23:10

Ich möchte den Codeschnipsel als Funktion einbauen.

Code: Alles auswählen

def check_date():                                                               
    last_day = min(datetime.date(year, 12, 31), datetime.date.today())     
    new_year, last_week, _ = day.isocalendar()                                  
    if new_year > year:       
        last_week = 52                                                          
    elif new_year < year:                        
        return         
Ich bekomme folgende Fehlermeldung:

Code: Alles auswählen

TickDataCsv.py|91 col 1 error| E0602 undefined name 'year' [pyflakes]                                                                                                                                              
TickDataCsv.py|91 col 1 error| W0612 local variable 'last_day' is assigned to but never used [pyflakes]
TickDataCsv.py|92 col 1 error| E0602 undefined name 'day' [pyflakes]
TickDataCsv.py|93 col 1 error| E0602 undefined name 'year' [pyflakes]
TickDataCsv.py|94 col 1 error| W0612 local variable 'last_week' is assigned to but never used [pyflakes]
TickDataCsv.py|95 col 1 error| E0602 undefined name 'year' [pyflakes]
Ich wollte die Funktion dann in der Funktion fetch_whole-year aufrufen.

Code: Alles auswählen

def fetch_whole_year(symbol, year):
      for symbol in symbol:
          check_date()
          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 Exception:
                  logger.exception("while downloading {}/{}/{}".format(
                      symbol, year, week)
                  )
              else:
                  logger.info("File for {}/{}/{} already fetched.".format(
                      symbol, year, week)
                  )
Sirius3
User
Beiträge: 17757
Registriert: Sonntag 21. Oktober 2012, 17:20

@aaron: lerne was Funktionen sind.
aaron
User
Beiträge: 92
Registriert: Donnerstag 1. Dezember 2016, 23:10

Ich versuche schon lange die Funktionen zu begreifen. Hier meine erste Frage. Als Parameter übergebe ich year und day, weil ich aktuelle Datum prüfen möchte. Ist 2017 > 2016, dann ist die letzte Woche die 52. Kalenderwoche. Was ist bei einem Jahr mit 53 Kalenderwochen? Ist das neue Jahr < Jahr dann return. Kann mir bitte jemand erklären wie diese Funktion richtig funktioniert, woher die Parameter kommen und wie diese richtig an die nächste Funktion übergeben werden.

Code: Alles auswählen

def check_date(year, day):
      last_day = min(datetime.date(year, 12, 31), datetime.date.today())
      new_year, last_week, _ = day.isocalendar()
      if new_year > year:
          last_week = 52
      elif new_year < year:
          return
Als Fehlermeldung bekomme ich

Code: Alles auswählen

TickDataCsv.py|91 col 1 error| W0612 local variable 'last_day' is assigned to but never used [pyflakes]                                                                                                            
TickDataCsv.py|94 col 1 error| W0612 local variable 'last_week' is assigned to but never used 
Sirius3
User
Beiträge: 17757
Registriert: Sonntag 21. Oktober 2012, 17:20

@aaron: was verstehst Du denn nicht (da hat es noch einen ziemlich offensichtlichen Fehler)? Zu welchem Zweck rufst Du die Funktion auf?
Benutzeravatar
pixewakb
User
Beiträge: 1412
Registriert: Sonntag 24. April 2011, 19:43

Ich habe die Diskussion nicht verfolgt. Möglicherweise macht es Sinn die Diskussionen (z. B. Logging-Problem) jeweils in neue Threads zu packen, so dass kleinere Einheiten (Diskussionnen) entstehen und man das später mittels Foren-Suche noch mal nutzen kann.

Code: Alles auswählen

def check_date(year, day):
      last_day = min(datetime.date(year, 12, 31), datetime.date.today())
      new_year, last_week, _ = day.isocalendar()
      if new_year > year:
          last_week = 52
      elif new_year < year:
          return
Zu den einzelnen Zeilen:
1. Du definierst eine Funktion check_date, die die beiden Parameter year und day erwartet.
2. Du ermittelst den last_day als Minimum zweier Daten, arbeitest in der Funktion aber nicht mehr (!) mit dieser Variable, was die Fehlermeldung 1 moniert.
3. Du bestimmst die Variablen new_year und last_week, nutzt aber die Variable last_week nicht mehr in der Funktion. Fehlermeldung 2. Ein echter Fehler, der zu einem Programmabbruch führen sollte, ist das beides nicht.
4. Du prüfst, ob das new_year größer als der Wert der Variable year ist und (5.) weist der Variablen last_week in diesem Fall den Wert 52 zu. Du verwendest diesen Wert in der Funktion sonst nicht mehr.
6. Ist new_year kleiner als year, dann machst du einen Rückgabewert ohne etwas zurückzugeben. Der Rückgabewert ist deshalb None.

Bei den Funktionen musst du verstehen, dass alles, was in der Funktion definiert und berechnet wird, dort bleibt (!), wenn es nicht zurückgegeben wird. Die Zuweisung in Zeile 5 z. B. ist wirkungslos, weil du damit weder weiterrechnest, noch etwas irgendwo veränderst (z. B. Prozedur), noch etwas zurückgibst.

Ich sehe nicht, dass die Funktion etwas leistet.
Antworten