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 snafu,

meinst Du etwa so:

Code: Alles auswählen

def package_to_python_paths(python_paths):
    """
    Erstellung der Python-Paketen aus den Python-Paden.
    """

    python_package = set()
    for path in python_paths:
        cmd = 'dpkg -S {} 2>nul'.format(path)
        proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
        result = proc.stdout.read().decode()
        package = result.split(':')[0]
        if package != '':
            python_package.add(package)
    return build_install_file(sorted(python_package))
Zu verschachtelt, wäre das die Lösung?:

Code: Alles auswählen

def main():
    python_paths = find_python_paths(search_in_files())
    python_package = package_to_python_paths(python_paths)
    build_install_file(python_package)

if __name__ == '__main__':
    main()
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Hallo Sirius3,

das mit dem Verschachteln, habe ich jetzt anhand Deines Codes verstanden.

Das mit filename.absolute() und den anderen Vorschlägen dazu, bekomme ich Fehlermeldungen.
Bei filename.absolute():

Code: Alles auswählen

TypeError: invalid file: PosixPath('/media/daten/officeplanet/firmware/build_sock_control.py')
Mein Pfad, sieht hingegen so aus:

Code: Alles auswählen

/media/daten/officeplanet/firmware/build_sock_control.py
Ich werde mich mal weiter durcharbeiten und poste ggf. Fehlermeldungen dazu.
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Ach, Du benutzt ja noch eine uralt-Pythonversion. Da braucht man noch eine explizite Konvertierung:

Code: Alles auswählen

search_import_names(str(filename))
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Sirius3 hat geschrieben: Mittwoch 22. August 2018, 15:59 Ach, Du benutzt ja noch eine uralt-Pythonversion. Da braucht man noch eine explizite Konvertierung:

Code: Alles auswählen

search_import_names(str(filename))
Ist Pythonversion 3.4 schon so alt, welche Version benutzt Du?

Poste nochmal Deinen Code, mit ein paar kleinen Abänderungen:

Code: Alles auswählen

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import ast
import subprocess
import pathlib
import importlib


def search_import_names(module):
    """
    Suche aus Python-Dateien importierte Python-Module.
    """

    import_names = set()
    with open(module) as content:
        tree = ast.parse(content.read())
    for node in ast.walk(tree):
        if isinstance(node, ast.Import):
            for alias in node.names:
                import_names.add(alias.name)
        elif isinstance(node, ast.ImportFrom):
            if node.level == 0:
                # ignore relative imports
                import_names.add(node.module)
    return import_names


def search_in_files():
    """
    Suche Python-Dateien innerhalb des Firmware-Ordners.
    """
    import_names = set()
    for filename in pathlib.Path('.').glob('**/*.py'):
        for module in search_import_names(str(filename)):
            import_names.add(module.split('.')[0])
    return import_names


def find_python_path(module):
    """
    Suche Python-Pfad aus den in der Firmware installiertem Modul.
    """

    try:
        loader = importlib.find_loader(module)
        return loader.path
    except (ImportError, AttributeError):
        # Module has no path, probably a builtin module
        print("No loader for", module)
        return


def package_to_python_path(path):
    """
    Erstellung Python-Paket aus den Python-Pfad.
    """

    cmd = ['dpkg', '-S', path]
    try:
        result = subprocess.check_output(cmd)
        package = result.decode().split(':')[0]
        return package
    except subprocess.CalledProcessError:
        print("no packages for", path)
        return


def main():
    modules = search_in_files()
    packages = set()
    for module in modules:
        path = find_python_path(module)
        if path is not None:
            package = package_to_python_path(path)
            if package:
                packages.add(package)
    print("Packages needed:")
    f = open('package_install_list.txt', 'w')
    for package in sorted(packages):
        print(package)
        f.write('{}\n'.format(package))
    f.close()
    return


if __name__ == '__main__':
    main()
Funktioniert prima!

Danke und Grüße Nobuddy
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Python 3.7 ist aktuell und 3.4 inzwischen 4 Jahre alt.
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Nobuddy hat geschrieben: Mittwoch 22. August 2018, 14:05 Zu verschachtelt, wäre das die Lösung?
Ich kann dir nicht DIE Lösung geben, einfach nur Erfahrungen weitergeben, da Programme schnell mal groß und unübersichtlich werden können. Manchmal kümmert man sich erst nach einem halben Jahr wieder um ein Modul. Und dann ist es gut, wenn man den Code wieder schnell versteht. Es ist ein Unterschied, ob man dann diese drölfzigfache Verschachtelung hat oder - wie von dir gezeigt - den Zusammenbau in einer main()-Funktion sehen kann.

Für die Maschine ist es am Ende egal, aber wir Menschen sollten uns das Leben nicht noch komplizierter machen... ;)
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Hallo snafu,

auch wenn etwas verspätet, möchte ich mich dazu nochmals melden.

Das was Du beschreibst, habe ich eingesehen und werde zukünftig mich bemühen, meinen Code lesbarer zu machen.

Danke und Grüße
Nobuddy
Antworten