ModuleNotFoundError Aber nicht immer

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.
Antworten
Valentin KS
User
Beiträge: 10
Registriert: Samstag 12. Dezember 2020, 14:28
Wohnort: Kassel

Hallo zusammen,
aktuell bin ich in meinem Pythonbuch im Kapitel JSON.
Diese kleine Skript:

Code: Alles auswählen

import json
from urllib.request import urlopen
ID = "365732826eb5f25bb6da21b0f4355337"             #1
URL = "http://api.openweathermap.org/data/2.5/weather?zip={},de&APPID={}"
REPORT = """
Wetterbericht für {}:
Temperatur: {:.1f} °C
Lufdruck: {:.1f} bar
""" 
print("Geben Sie die Postleitzahl einer Stadt in Deutschland ein.")
city = input("PLZ: ")
while city:                                         #3
    try:
        f = urlopen(URL.format(city, ID))               #4
        data = json.load(f)                         #5
        name_city = data["name"]
        temp = data["main"]["temp"]-273.15          #6
        pressure = data["main"]["pressure"]
        print(REPORT.format(name_city, temp, pressure)) #7
    except:
        print("Fehler. Vielleicht war die Postleitzahl ungültig.")    
    city = input("PLZ: ")
print("Auf Wiedersehen!")
bereitet mir jedoch Kopfschmerzen.

Öffne ich das Skript aus dem Download funktioniert es einwandfrei.
Wenn ich aber ein neues Fenster öffne und den Text abtippe oder auch direkt rüber kopiere funktioniert es nicht.
Diesen Fehler erhalte ich:

Code: Alles auswählen

Python 3.8.10 (default, Sep 28 2021, 16:10:42) 
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license()" for more information.
>>> 
======= RESTART: /mnt/sda5/scripts/python/Buch/26 XML und JSON/wetter.py =======
Traceback (most recent call last):
  File "/usr/lib/python3.8/idlelib/run.py", line 559, in runcode
    exec(code, self.locals)
  File "/mnt/sda5/scripts/python/Buch/26 XML und JSON/wetter.py", line 8, in <module>
    from urllib.request import urlopen
  File "/usr/lib/python3.8/urllib/request.py", line 88, in <module>
    import http.client
  File "/usr/lib/python3.8/http/client.py", line 71, in <module>
    import email.parser
ModuleNotFoundError: No module named 'email.parser'; 'email' is not a package
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/apport_python_hook.py", line 72, in apport_excepthook
    from apport.fileutils import likely_packaged, get_recent_crashes
  File "/usr/lib/python3/dist-packages/apport/__init__.py", line 5, in <module>
    from apport.report import Report
  File "/usr/lib/python3/dist-packages/apport/report.py", line 21, in <module>
    from urllib.request import urlopen
  File "/usr/lib/python3.8/urllib/request.py", line 88, in <module>
    import http.client
  File "/usr/lib/python3.8/http/client.py", line 71, in <module>
    import email.parser
ModuleNotFoundError: No module named 'email.parser'; 'email' is not a package
Wie kann das passieren? Müssten sich nicht beide gleich verhalten?
Habe bereits den Rechner neu gestartet und Python neu installiert.

Schönen Dank schon mal an all die die ich ins grübeln gebracht habe.
Benutzeravatar
sparrow
User
Beiträge: 4540
Registriert: Freitag 17. April 2009, 10:28

Hast du eine Datei namens email.py?
Dann wird die statt des packages importiert.
Benutzeravatar
__blackjack__
User
Beiträge: 14076
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Valentin KS: Die Ausnahmebehandlung in dem Beispiel ist extrem schlecht. Da wird *jede* Ausnahme in die Ausgabe das vielleicht die Postleitzahl ungülitig war, umgewandelt. Also auch wenn keine Netzwerkverbindung zustande kam, und sogar wenn Du Dich irgendwo in dem ``try``-Block bei einem Namen vertippt hast. Solche Fehler sind dann nur sehr mühsam zu finden. Bei Ausnahmebehandlung sollte man nur Ausnahmen behandeln, bei denen die gewählte Behandlung Sinn macht. Und eine Behandlung für *jede mögliche* Ausnahme ist selten sinnvoll.

Wenn man vor einer ``while``-Schleife einen Namen der in der Bedingung verwendet wird, mit einem Dummy-Wert belegt, oder den Code für die Belegung in der Schleife noch mal wiederholt, dann ist das eigentlich eine “Endlosschleife“, also ``while True:``, die man dann mit einem entsprechenden Test und ``break`` abbricht.

Eine Postleitzahl steht nicht für eine Stadt, also ist der Name `city` schlecht gewählt.

Dateien die man öffnet, sollte man auch wieder schliessen. Wenn das Dateiobjekt ein Kontextmanager ist, verwendet man die ``with``-Anweisung dafür.

Einbuchstabe Namen sind in der Regel keine gute Namen. Wenn man `file` meint, sollte man nicht nur `f` schreiben.

`name_city` sagt vielleicht Meister Yoda.

`temp` ist komisch. Warum ist der Wert dort Temporär und bekommt keinen Namen der die Bedeutung widerspiegelt‽

Wenn man irgendwo von einer Zahl eine magische 273.15 abzieht, würde ich kommentieren was das soll. Ist nicht jedem sofort ersichtlich.

Ungetestet:

Code: Alles auswählen

#!/usr/bin/env python3
import json
from urllib.request import urlopen

ID = "365732826eb5f25bb6da21b0f4355337"
URL = "http://api.openweathermap.org/data/2.5/weather?zip={},de&APPID={}"
REPORT = """
Wetterbericht für {}:
Temperatur: {:.1f} °C
Lufdruck: {:.1f} bar
"""


def main():
    print("Geben Sie die Postleitzahl einer Stadt in Deutschland ein.")
    while True:
        postal_code = input("PLZ: ").strip()
        if not postal_code:
            break
        with urlopen(URL.format(postal_code, ID)) as file:
            data = json.load(file)
        city_name = data["name"]
        temperature = data["main"]["temp"] - 273.15  # Kelvin → C°.
        pressure = data["main"]["pressure"]
        print(REPORT.format(city_name, temperature, pressure))

    print("Auf Wiedersehen!")


if __name__ == "__main__":
    main()
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Valentin KS
User
Beiträge: 10
Registriert: Samstag 12. Dezember 2020, 14:28
Wohnort: Kassel

sparrow hat geschrieben: Sonntag 7. November 2021, 15:49 Hast du eine Datei namens email.py?
Dann wird die statt des packages importiert.
Nein, habe ich nicht.
Das große Fragezeichen ist aber auch warum funktioniert die Datei aus dem Download aber nicht die von mir getippte.
Wie gesagt, wenn ich ein neues Fenster öffne und die Zeilen dann dort eingebe geht's nicht mehr.
Bild
Das Skript links läuft, das rechts macht den Fehler.
Valentin KS
User
Beiträge: 10
Registriert: Samstag 12. Dezember 2020, 14:28
Wohnort: Kassel

@__blackjack__: Ja, das Buch ist in einigen Punkten hier nicht beliebt, die Hinweise lese ich immer wieder.
Dein Vorschlag verursacht die selbe Fehlermeldung. Zumindest im rechten Fenster. Im linken geht's.
Genau das ist mein Problem.
Öffne ich die Datei aus dem Download geht's, schreib ich's selbst geht's nicht.
Es müssten ja auch beide auf die selben Pakete zugreifen, also auf dem selben JSON und urllib.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du hast da irgendwo eine email.pyc rum liegen. Versuch mal rechts ein simples “import email;print(email)” als erste Anweisung.
Valentin KS
User
Beiträge: 10
Registriert: Samstag 12. Dezember 2020, 14:28
Wohnort: Kassel

__deets__ hat geschrieben: Sonntag 7. November 2021, 17:50 Du hast da irgendwo eine email.pyc rum liegen. Versuch mal rechts ein simples “import email;print(email)” als erste Anweisung.
ändert auch nichts, leider.
Sirius3
User
Beiträge: 18278
Registriert: Sonntag 21. Oktober 2012, 17:20

Das soll ja auch nichts ändern, sondern Dir zeugen, wo Deine email.py-Datei liegt, die fälschlicherweise genommen wird, statt des email-Pakets aus der Standardbibliothek.
Valentin KS
User
Beiträge: 10
Registriert: Samstag 12. Dezember 2020, 14:28
Wohnort: Kassel

Sirius3 hat geschrieben: Sonntag 7. November 2021, 18:38 Das soll ja auch nichts ändern, sondern Dir zeugen, wo Deine email.py-Datei liegt, die fälschlicherweise genommen wird, statt des email-Pakets aus der Standardbibliothek.
Oh. :cry: :oops: die hab ich übersehen.
Nachdem ich die verschoben habe geht's.

Danke an alle Beteiligten.
Antworten