pobieranie i instalowanie zależności (dpkg), dopóki wszystkie nie zostaną spelnione

0

Mam problem jak w tytule.
W dużym skrócie piszę program w Python 3, którego jednym z zadań jest pobieranie pakietu z podanego adresu url bazując na słowniku ( {'pakiet': {'filename': 'pakiet.deb'}, {'pakiet2': {'filename': 'pakiet2.deb'}} )

Przykładowa funkcja:

def install(self, display_name, filename):

        print(" Installing...")
        print(" ")
        filepath = os.path.join("/opt/MeeShop/.cache", filename)
        command = 'LANG=C aegis-dpkg -i "{}"'.format(filepath)
        try:
            result = subprocess.check_output(command, shell=True, stderr=subprocess.STDOUT)
        except subprocess.CalledProcessError as e:
            result = e.output
        result = result.decode("utf-8")
        depends = re.findall("depends on (.+);", result)
        if depends:
            depends = ', '.join(depends)
            print(" Package {} depends on following\n dependencies, not installed yet: {}.format(display_name, depends))

        print(" ")
        print(" {}{} installed!{}".format(green, display_name, reset))
        input(" {}{}Press Enter to continue... {}".format(blink, cyan, reset))


Jak widzicie potrafi już znaleźć brakujące zależności.
Teraz jest haczyk.

Skrypt ma dla każdej zależności pobierać ją (w sensie np. zależność to 'pakiet3' to znajduje ją w słowniku pakiety i ściąga wartość filename ( packages[dependency]['filename'] ), zapisywać i instalować za pomocą install (w klasie Apt). Ale jeśli dana zależność podczas instalacji wymaga innych zależności, je też ma pobierać i instalować. Itp. itd.
Dopóki WSZYSTKIE pierwotne zależności nie zostaną zainstalowane, i nie będzie żadnych problemów zależności.
Pokręcone, ale taka jest sprawa.

I nie wiem jak mam to zrobić. Aby pętla trwała dopóki powyższe nie zostanie spełnione.
Jakieś pomysły?
Z góry dzięki

Pozdrawiam

0

Jakby co to:

blink, cyan, reset to kody kolorków terminala
aegis-dpkg to dpkg

0

Można to zrobić za pomocą rekurencji - funkcji, która wywołuje samą siebie aż do momentu, kiedy wszystkie zależności zostaną zainstalowane.

W Twoim przypadku, funkcja install() powinna wywoływać się rekurencyjnie dla każdej nowej zależności, aż do momentu, kiedy wszystkie zależności zostaną zainstalowane. W takim przypadku funkcja install() musi sprawdzać zależności dla każdego pakietu, który próbuje zainstalować i wywoływać się rekurencyjnie, jeśli jakieś zależności nie zostały jeszcze zainstalowane.

class Apt:
    def __init__(self, packages):
        self.packages = packages

    def install(self, display_name):
        print("Installing... {}".format(display_name))

        package = self.packages[display_name]
        filename = package['filename']
        filepath = os.path.join("/opt/MeeShop/.cache", filename)
        command = 'LANG=C aegis-dpkg -i "{}"'.format(filepath)
        try:
            result = subprocess.check_output(command, shell=True, stderr=subprocess.STDOUT)
        except subprocess.CalledProcessError as e:
            result = e.output
        result = result.decode("utf-8")
        depends = re.findall("depends on (.+);", result)
        if depends:
            depends = depends[0].split(', ')
            for dependency in depends:
                if dependency not in self.packages:
                    raise Exception("Dependency {} not found!".format(dependency))
                self.install(dependency)
            self.install(display_name)
        else:
            print("{} installed!".format(display_name))

    def install_all(self):
        for package_name in self.packages:
            self.install(package_name)


Funkcja install() jest wywoływana dla każdego pakietu, który próbujesz zainstalować. Jeśli pakiet ten wymaga innych zależności, funkcja install() wywołuje się rekurencyjnie dla każdej z tych zależności, aż do momentu, kiedy wszystkie zależności zostaną zainstalowane. W przypadku braku zależności funkcja po prostu instaluje pakiet.

Funkcja install_all() służy do instalacji wszystkich pakietów na raz. Można go użyć, aby zainstalować wszystkie pakiety z jednym wywołaniem funkcji.

Oczywiście, funkcja ta nie jest optymalna pod względem wydajności, ponieważ w przypadku dużej liczby zależności może dochodzić do wielokrotnych pobierania tych samych zależności. Jednak w przypadku niewielkiej liczby pakietów i zależności powinna działać wystarczająco dobrze.

0

Dzięki!
Działa idealnie, i mega się przydaje. Sorki za opóźnienie 7 miesięcy w odpowiedzi xD

1 użytkowników online, w tym zalogowanych: 0, gości: 1