Welches Python-Paket steckt hinter Import ...

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.
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Hallo zusammen,

gibt es eine automatisierte Lösung, bei Python-Scripten bei der Import-Funktion "from .... import ...", das Python-Paket herauszufinden?

Grüße Nobuddy
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Kannst du mal mehr ausführen was du da genau da erreichen willst?
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Hallo __deets__,

Habe ein größeres Python-Projekt und möchte feststellen, welche Python-Pakete dazu benötigt werden.
python3, python3-minimal und python-reportlab habe ich schon ausgemacht.
Um evtl. weiter benötigte Python-Pakete ausfindig zu machen, möchte meine programmierten Module abfragen.

Dazu ein kleines Beispiel:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# For Python3.x


import copy
import tkinter as tk
from functools import partial
from datetime import date
Zu welchem Python-Paket gehört copy, tkinter, fuctools, datetime .... ?
Damit könnte ich dann genau festlegen, welche Python-Pakete installiert sein müssen, um mein Python-Projekt funktionsfähig zu machen.

Grüße Nobuddy
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ah. Mit dem ast-Modul kannst du dir prinzipiell die import-statements rausloeten aus deinem Code, und dann die Paket/Modulnamen bekommen. Das Problem ist, dass die nicht unbedingt eindeutig zu einem PyPi-Modul zuzuordnen sind. Das faengt mit dem Namen an. Import foo kann aus dem Paket "pyfoo" kommen, oder aus "FooDingeDieTollSind" - da gibt es keine Vorgaben. Und selbst *wenn* du das heuristisch aufloest, hast du immer noch das Problem, dass du die benoetigte Version nicht ablesen kannst.

Vernuenftige Projekte machen das genau umgekehrt - die haben eine requirements.txt, in der die zu installierenden Pakete aufgefuehrt sind, Version inklusive. Unter Umstaenden ist auch ein Blick in setup.py erhellend.
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Ja, das habe ich leider verschlafen, das rächt sich nun ...., werde es aber versuchen nachzupflegen!

Könnte es sein dass, Paket/Modulnamen sich auf die im Betriebssystem liegenden Paket bezieht?
Muss das mal mit dem ast-Modul testen, vielleicht komme ich da doch noch auf einen "grünen Zweig" ...

Grüße Nobuddy
Benutzeravatar
__blackjack__
User
Beiträge: 13079
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Es geht hier ja gar nicht um PyPI-Pakete sondern um Debian/Ubuntu-Pakete. Da hilft auch eine `requirements.txt` nur bedingt.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Die wuerde denke ich immer noch helfen. Denn das deb ist eher nach dem Paketnamen und nicht dem import-Namen benannt, und auch die Version kann man ablesen. Man kann halt pip nicht benutzen.
Benutzeravatar
__blackjack__
User
Beiträge: 13079
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Deswegen schrob ich ja „bedingt“ und nicht „gar nicht“. :-)
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

@Nobuddy: ich würde gar keine DEB-Pakete für so was benutzen sondern alles via pip installieren. Gründe: bessere Kontrolle über die Version des Python-Moduls unabhängig vom Betriebssystem bzw. in deinem Falle der *buntu-Version, keine systemweite Installations nötig, besser in Virtual Environments kapselbar, besser updatebar, wenn du die Features einer neueren Version des Python-Modul brauchst.

Bei Ubuntu liegen ja sehr viele Python-Pakete in 'universe' in einer vergleichsweise alten Version und bekommen so wie so keine selten Updates. Die Probleme hast du mit pip nicht.

Gruß, noisefloor
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@noisefloor:
Und was machst du, wenn ein vom System genutztes Paket ein Update erhält, welches nicht abwärtskompatibel ist und es dadurch bei einem wichtigen Skript knallt? Ich würde solche Tipps daher mit Vorsicht genießen. Wenn es ausschließlich um virtuelle Umgebungen geht, dann ist es okay, aber bei der systemseitig genutzten Interpreter-Version würde ich mir das lieber dreimal überlegen.
Benutzeravatar
pixewakb
User
Beiträge: 1412
Registriert: Sonntag 24. April 2011, 19:43

Ich habe mir für so einen Zweck ein Tool geschrieben, dass die py- und pyw-Skripte in einem Verzeichnis ausliest und alle Zeilen mit einem 'import' auswirft. Unter Windows und mit pip habe ich dann pip freeze in die Konsole eingegeben und konnte die Pakete und die Versionen auslesen (das scheint bei dir nicht zu gehen). Der Ansatz findet auch Importe, die sich irgendwo in einer Test-Funktion eines Skripts befinden, was bei mir seltenst vorkommt.

Die Importe, die du oben ausführst, scheinen doch alle aus der Standardbibliothek zu kommen. Außer bei bs4 finde ich die Namen eigentlich immer eindeutig, d. h. ich verstehe schnell, was das für ein Modul ist. Importierte Module haben bei mir eigentlich nie den Namen eines fertigen Moduls, dass ich über pypi laden könnte.
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

@snafu: ich verstehe deinen Punkt nicht. Noisefloor schlägt venvs und pip vor. Womit man am unabhängigsten vom Paketmanagement ist. Gerade dein Szenario mit dem neuen Systempaket wird dadurch doch adressiert? Und was hat das mit dem Systeminterpreter zu tun? Den benuzt man doch zu 99%, aber dank System Paket Isolation ohne Probleme.

Wenn natürlich zb C++ /C Bibliotheken sich ändern, kann es immer noch zu Problemen kommen. Dann hilft ggf Containerisierung oder die neuen Anwendungsformate flatpack etc.
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Hallo zusammen,

ich glaube nicht, dass ast die richtige Wahl ist, um die für mein Projekt benötigte Python-Pakete feststellen zu können.

Das mit pip und virtualenv, ist wohl einer der Alternativen, um zukünftig nicht mehr vor diesen Problemen stehen zu müssen.
Leider habe ich versäumt, eine Dokumentation für die notwendigen zu installierenden Python-Paketen zu erstellen.

Ich werde mal eine Liste mit den importierten Python-Modulen erstellen.
Vielleicht hat ja jemand von Euch noch eine Idee dazu?

Grüße Nobuddy
Benutzeravatar
pixewakb
User
Beiträge: 1412
Registriert: Sonntag 24. April 2011, 19:43

Code: Alles auswählen

        # Importe
        if "import" in line:
            auswertung["import"].append((i, prettify_code_line(line)))
Das habe ich gemacht und mir dann die Ergebnisse in ein HTML-Dokument gekippt, allerdings gibt es bei meinem Skript da viele interne Abhängigkeiten zu internen Modulen für die Generierung von HTML-Dokumenten und spezielle Fragen, die beantwortet werden mussten.

Mit so etwas könnte man sich Listen der installierten Module machen und dann nach Standardbibliothek und Fremdpaketen unterscheiden. Bei mir reduziert(e) sich die Zahl der interessanten Fremdpakete deutlich - pip freeze liefert bei mir eine lange Liste, aber das hat wesentlich mit den Abhängigkeiten der einzelnen Module zu tun...
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

@snafu: Schließe mich __deets__ an - den Punkt
Und was machst du, wenn ein vom System genutztes Paket ein Update erhält, welches nicht abwärtskompatibel ist und es dadurch bei einem wichtigen Skript knallt?
verstehe nichts, also welches Szenario da entstehen soll. Bitte mal ausführlicher erklären und ein Beispiel. Thx.

Gruß, noisefloor
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Ich verstehe nicht so ganz, wo das große Problem ist. Ein einfaches grep

Code: Alles auswählen

grep -r --include '*.py' -h '\bimport\b' . | sort -u
sollte eine Liste aller Importzeilen liefern, die man leicht händisch durchgehen kann.
Relevant ist ja nur die oberste Ebene, die man dank Sortierung schnell findet.
Das kann man noch mit der Liste der eigenen und der Standardmodule (https://docs.python.org/3/library/) abgleichen.

Was übrig bleibt, dürfte nicht mehr all zu viel sein. Im Zweifel mit

Code: Alles auswählen

import xyz
print(xyz.__file__)
nach dem Pfad fragen und den Paketmanager bitten, das Paket zu nennen, das diese Datei installiert hat.
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Habe das soweit umgesetzt, dass ich jetzt alle Importe die Python betrifft, in einer Liste vorliegen.
Beim Versuch, diese weiter zu verarbeiten:

Code: Alles auswählen

    for modul in sorted(python_moduls):
        import modul
        print(modul.__file__)
erhalte ich die Fehlermeldung:

Code: Alles auswählen

ImportError: No module named 'modul'
was ja auch klar sein dürfte.

Nun habe ich die Frage an Euch, ob es eine Möglichkeit gibt, dies in dieser Art umsetzen zu können?
Ein automatisierter Ablauf, wäre ja von Vorteil.

Weiter habe ich manuell, mit zwei Beispielen getan:
import sys
sys.__file__
# Ergebnis: AttributeError: 'module' objects has no attribute '__file__'

import reportlab
reportlab.__file__
# Ergebnis: /usr/lib/python3/reportlab/__init__.py
Was kann man tun, um bei z.B. 'sys', ein Ergebnis zu erhalten?
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Zu Punkt 1, habe ich diese Lösung gefunden:

Code: Alles auswählen

    for modul in sorted(python_moduls):
        try:
            print(__import__(modul).__file__)
        except AttributeError:
            pass
        except ImportError:
            pass
Fragt sich nur, was es für den 'AttributeError' und den 'ImportError' für eine Lösung gibt, um auch hier ein Ergebnis zuerhalten?
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Ich poste mal meine Ergebnisse:

Code: Alles auswählen

####### python_paths #######
['/usr/lib/python3.4/codecs.py',
 '/usr/lib/python3.4/collections/__init__.py',
  '/usr/lib/python3.4/copy.py', 
  '/usr/lib/python3.4/csv.py',
   '/usr/lib/python3.4/datetime.py',
    '/usr/lib/python3.4/ftplib.py',
     '/usr/lib/python3.4/functools.py',
      '/usr/lib/python3.4/io.py',
       '/usr/lib/python3.4/json/__init__.py',
        '/usr/lib/python3.4/os.py',
         '/usr/lib/python3.4/platform.py',
          '/usr/lib/python3.4/queue.py',
           '/usr/lib/python3.4/re.py',
            '/usr/lib/python3.4/shutil.py',
             '/usr/lib/python3.4/smtplib.py',
              '/usr/lib/python3.4/socket.py',
               '/usr/lib/python3.4/subprocess.py',
                '/usr/lib/python3.4/threading.py',
                 '/usr/lib/python3.4/tkinter/__init__.py',
                  '/usr/lib/python3.4/urllib/__init__.py',
                   '/usr/lib/python3.4/zipfile.py',
                    '/usr/lib/python3/dist-packages/cups.cpython-34m-x86_64-linux-gnu.so',
                     '/usr/lib/python3/dist-packages/lxml/__init__.py',
                      '/usr/lib/python3/dist-packages/reportlab/__init__.py',
                       '/usr/lib/python3/dist-packages/requests/__init__.py',
                        '/usr/lib/python3/dist-packages/urllib3/__init__.py',
                         '/usr/lib/python3/dist-packages/xlrd/__init__.py']

####### AttributeError_names #######
[('atexit', <module 'atexit' (built-in)>), 
('sys', <module 'sys' (built-in)>),
 ('time', <module 'time' (built-in)>)]
Vielleicht könnt Ihr mir einen Tip geben, wie ich jetzt weiter komme?
Benutzeravatar
pixewakb
User
Beiträge: 1412
Registriert: Sonntag 24. April 2011, 19:43

Ich habe mal deinen Quellcode für einige bei mir installierte Pakete genutzt:

Code: Alles auswählen

for modul in sorted(["random", "os", "sys", "pandas", "something"]):
    try:
        print(__import__(modul).__file__)
    except AttributeError:
        pass
    except ImportError:
        pass
Liefert dann bei mir:

Code: Alles auswählen

C:\[...]\Python\Python37\lib\os.py
C:\[...]\Python\Python37\lib\site-packages\pandas\__init__.py
C:\[...]\Python\Python37\lib\random.py
C:\[...]\Python\Python37\lib\site-packages\something.py
Ich schließe daraus, dass im Ordner site-packages Module gelandet sind, die du selbst installiert hast und unter lib direkt die Standardbibliothek zu finden ist.

Die folgenden Module müsstest du bei dir mal prüfen, alles andere sieht für mich nach Standardbibliothek aus.:

Code: Alles auswählen

                    '/usr/lib/python3/dist-packages/cups.cpython-34m-x86_64-linux-gnu.so',
                     '/usr/lib/python3/dist-packages/lxml/__init__.py',
                      '/usr/lib/python3/dist-packages/reportlab/__init__.py',
                       '/usr/lib/python3/dist-packages/requests/__init__.py',
                        '/usr/lib/python3/dist-packages/urllib3/__init__.py',
                         '/usr/lib/python3/dist-packages/xlrd/__init__.py']
requests und xlrd (https://pypi.org/project/xlrd/) sind m. E. sicher Fremdbibliotheken, die du installiert hast. atexit, sys und time sind Teil der Standardbibliothek (https://docs.python.org/3.7/library/atexit.html).
Antworten