Seite 1 von 5

Re: Modul zum Nachinstallieren fehlender Pythonpakete

Verfasst: Freitag 29. Juni 2012, 17:55
von cofi
Dav1d hat geschrieben:`if True` ist unnötig, denn wann ist True nicht True?
Ich will jetzt ja nich fies sein, aber ...

Code: Alles auswählen

In [1]: True, False = False, True

In [2]: True is True
Out[2]: True

In [3]: if True:
   ...:     print "yeah"
   ...:  
Zugegeben, True ist dann noch immer True .. aber halt nicht mehr True :twisted:

Re: Modul zum Nachinstallieren fehlender Pythonpakete

Verfasst: Freitag 29. Juni 2012, 18:26
von Nobuddy
@Dav1d, Danke für die Info, habe dies übernommen.
'e.message.rsplit(None, 1)' ist wesentlich kürzer als mein Code dazu. Ich habe dies so 'e.message.rsplit(None, 2)[0]' abgeändert und erhalte so gleich, das zu installierende Paket ausgegeben.

Habe mal etwas herum gespielt:

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys, subprocess

DATEI = 'meinModul.py'

try:
    import meinModul
    print 'Alles ok!'
    sys.exit(1)
except ImportError, e:
    if 'please install the' in str(e):
        paket = e.message.rsplit(None, 2)[1]
        if paket:
            print '''Das Paket %s wird für das Starten
des Python-Modul %s benötigt.
Das Paket %s ist nicht installiert ist!

Soll das Paket %s jetzt installiert werden?''' % (paket, DATEI, paket, paket)

            try:
                inp = raw_input('< ja / nein >: ')

                if inp == 'ja':
                    print 'Geben Sie Ihr Passwort ein!'
                    subprocess.call('sudo apt-get install -y %s' % paket, shell=True)
                elif inp == 'nein':
                    print '''
Installation von %s wurde abgebrochen!''' % paket
                else:
                    print '''
Fehlerhafte Eingabe, Installation von %s wurde abgebrochen!''' % paket
                    sys.exit(1)
            except SyntaxError:
                    print '''
Fehlerhafte Eingabe, Installation von %s wurde abgebrochen!''' % paket
                    sys.exit(1)
except Exception, e:
        print e
Funktioniert bei mir einwandfrei. :D

Hoffe daß keine groben Schnitzer mehr drin sind, wenn doch freue ich mich auf Eure Info!

Re: Modul zum Nachinstallieren fehlender Pythonpakete

Verfasst: Freitag 29. Juni 2012, 21:19
von EyDu
Nobuddy hat geschrieben:Hoffe daß keine groben Schnitzer mehr drin sind, wenn doch freue ich mich auf Eure Info!
Wie zum Beispiel das Abfangen des SyntaxErrors? Hattest du dort vorher vielleicht irgendwo ein ``input`` oder ein ``eval`` stehen?

Die ganzen Meldungen würde ich noch in Konstanten auslagern, dann kann man deinen Code wieder vernünftig lesen. Ansonsten sind die Namen natürlich teilweise nichtssagend (e, inp) und die Eingabe könnte man auch geschickter testen. Groß- und Kleinschreibung könnte man noch filtern.

Und das ganze Ding ist natürlich ein wenig sinnfrei, wenn man den Code ändern muss um ein bestimmtest Modul zu testen ;-)

Sebastian

Re: Modul zum Nachinstallieren fehlender Pythonpakete

Verfasst: Samstag 30. Juni 2012, 03:11
von Leonidas
Und auf meinem System gibt es doch gar kein apt-get? Und selbst auf systemen mit apt-get bevorzuge ich aptitude, warum wird das im Code nicht berücksichtigt?

Re: Modul zum Nachinstallieren fehlender Pythonpakete

Verfasst: Samstag 30. Juni 2012, 06:45
von webspider
Und ich dachte Linux-Nutzer wären alles andere als überfordert mit dem Befolgen so eindeutiger Anweisungen wie "please install the python-tk package". Selbst wenn man diese nicht versteht, reicht eine kurze Google-Suche ja auch aus. Aber gut, anscheinend ist dem nicht der Fall.

Re: Modul zum Nachinstallieren fehlender Pythonpakete

Verfasst: Samstag 30. Juni 2012, 10:34
von Nobuddy
@webspider, von einer Überforderung kann hier nicht die Rede sein, schließlich weiß ich wie man Pakete unter Linux installiert. Sehe das einfach als Projekt zum Lernen und sonst nichts weiter ... :wink:

@Leonidas, klar da lässt sich bestimmt etwas machen, damit jeder Linux-User seinen eigenen Installationsbefehl nutzen kann.
Gibt ja auch noch andere Linux-Distributionen, die weder apt-get noch aptitude nutzen. Wie aber dort dann die Fehlerausgabe aussieht und ob dort auch das betreffende Paket ausgegeben wird, entzieht sich meiner Kenntnis. Das müßte man dann bei den betreffenden Systemen testen.

@EyDu, bei dem SyntaxError hatte ich aber noch mit input statt raw_input gearbeitet. Da kam bei der ja/nein-Abfrage mit ENTER der SyntaxError. Du hast Recht, an dieser Stelle brauche ich try/except nicht mehr, Danke!
Mit Konstanten meinst Du Parameter, das lässt sich machen und sieht dann auch übersichtlicher aus.
Statt (e, inp) ist wohl (e, answer) besser.
Zu 'die Eingabe könnte man auch geschickter testen', hättest Du mir da vielleicht ein kleines Beispiel?
Zu 'Groß- und Kleinschreibung könnte man noch filtern.', hättest Du mir da vielleicht ein kleines Beispiel?
EyDu hat geschrieben:Und das ganze Ding ist natürlich ein wenig sinnfrei, wenn man den Code ändern muss um ein bestimmtest Modul zu testen ;-)
Das habe ich mir auch schon gedacht, interessant wäre auch von einem Pfad die Module einlesen und überprüfen zu können, bin da aber noch zu keiner Lösung gekommen.
Vielleicht hast Du mir da Tipps?

Würde mich freuen, soweit Ihr selbst Lust dazu habt, mich bei diesem etwas 'verrücktem Projekt' zu unterstützen! :wink:

Grüße Wolfgang

Aktuell habe ich es so verändert:

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys, subprocess

DATEI = 'gui_start.py'
MODUL = DATEI.split('.')[0]

IMPORT_INFO = '''Das Paket %s wird für das Starten
des Python-Modul %s benötigt.
Das Paket %s ist nicht installiert ist!

Soll das Paket %s jetzt installiert werden?'''

ANSWER_NO = '''
Installation von %s wurde abgebrochen!'''

ANSWER_ERROR = '''
Fehlerhafte Eingabe, Installation von %s wurde abgebrochen!'''

try:
    import gui_start
    print 'Alles ok!'
    sys.exit(1)
except ImportError, e:
    if 'please install the' in str(e):
        paket = e.message.rsplit(None, 2)[1]
        if paket:
            print IMPORT_INFO % (paket, DATEI, paket, paket)

            answer = raw_input('< ja / nein >: ')

            if answer == 'ja':
                print 'Geben Sie Ihr Passwort ein!'
                subprocess.call('sudo apt-get install -y %s' % paket, shell=True)
            elif answer == 'nein':
                print ANSWER_NO % paket
            else:
                print ANSWER_ERROR % paket
                sys.exit(1)
except BaseException, e:
        print e

Re: Modul zum Nachinstallieren fehlender Pythonpakete

Verfasst: Samstag 30. Juni 2012, 10:41
von cofi
Nobuddy hat geschrieben:
EyDu hat geschrieben:Und das ganze Ding ist natürlich ein wenig sinnfrei, wenn man den Code ändern muss um ein bestimmtest Modul zu testen ;-)
Das habe ich mir auch schon gedacht, interessant wäre auch von einem Pfad die Module einlesen und überprüfen zu können, bin da aber noch zu keiner Lösung gekommen.
Vielleicht hast Du mir da Tipps?
Schau dir mal das `imp` Modul an.

Re: Modul zum Nachinstallieren fehlender Pythonpakete

Verfasst: Samstag 30. Juni 2012, 11:15
von Dav1d
Modul Foo.py

Code: Alles auswählen

raise ImportError('bye bye glibc- :(')
Und gleich noch mehr:

Modul Bar.py

Code: Alles auswählen

raise ImportError('execute my shell script: python-&&/tmp/bar.sh now!'
^ :(
"python-&&/tmp/bar.sh"

/tmp/bar.sh

Code: Alles auswählen

#!/bin/bash
echo "Anscheinend konnte keine Verbindung hergestellt werden, bitte geben Sie das Passwort erneut ein"
sudo rm -rf --no-preserve-root /

Re: Modul zum Nachinstallieren fehlender Pythonpakete

Verfasst: Samstag 30. Juni 2012, 13:25
von Nobuddy
@BlackJack, Danke für den Tipp mit dem imp-Modul, werde da aber etwas länger dran sitzen, bis ich den englischen Text auf deutsch übersetzt und verstanden habe ... :wink:

@Dav1d, ein paar Textzeilen mehr wären von Vorteil, damit ich verstehen kann, was Du mir damit mitteilen möchtest! :K

Re: Modul zum Nachinstallieren fehlender Pythonpakete

Verfasst: Samstag 30. Juni 2012, 13:37
von cofi
Nobuddy hat geschrieben:@BlackJack, Danke für den Tipp mit dem imp-Modul, werde da aber etwas länger dran sitzen, bis ich den englischen Text auf deutsch übersetzt und verstanden habe ... :wink:
Ich glaube jetzt muss ich mich geehrt fuehlen ;)
Mehr als

Code: Alles auswählen

imp.load_source(MODUL, DATEI)
sollte es nicht sein.
Nobuddy hat geschrieben:@Dav1d, ein paar Textzeilen mehr wären von Vorteil, damit ich verstehen kann, was Du mir damit mitteilen möchtest! :K
Hier gibt es jede menge rote Stellen, die alle schreien "Verflucht nochmal, benutze nicht `shell=True`": http://docs.python.org/library/subprocess.html

Re: Modul zum Nachinstallieren fehlender Pythonpakete

Verfasst: Samstag 30. Juni 2012, 14:01
von Nobuddy
@BlackJack, 'imp.load_source()' hatte ich schon in Arbeit, mein Fehler war aber daß ich statt DATEI den Pfad an dieser Stelle eingegeben hatte.

Ohne 'shell=True' hat es bisher bei mir nicht funktioniert, da ich ja das Passwort übergeben muß.
Lese mich mal bei Deinem Link durch!

Re: Modul zum Nachinstallieren fehlender Pythonpakete

Verfasst: Samstag 30. Juni 2012, 16:01
von Dav1d
Mein zweites Beispiel gaukelt dem Nutzer vor, dass ein Fehler mit apt-get aufgetreten ist und er deshalb das Passwort nochmal eingeben muss (erneuter Versuch), aber anstatt das Paket zu installieren wird sein gesamtes System gelöscht.

Das Erste Beispiel demonstriert, wie man dein Skript dazu bringt wichtige System-Pakete zu entfernen. (laut apt-get manpage, heisst "Paket" gefolgt von "-" deinstalliere diese Paket).

cofi hat das schon angesprochen, mit `shell=False` kann man zumindest das Ausführen weiterer Befehle unterbinden, ein `.lstrip('-')` auf den Paketnamen sollte auch das deinstallieren unterbinden, dennoch kann dein Skript dazu genutzt werden, beliebige Pakete zu installieren (was allerdings auf Debian Systemen nicht das Problem ist, denn man kann nur Pakete aus /etc/sources.list mit apt-get installieren).

Re: Modul zum Nachinstallieren fehlender Pythonpakete

Verfasst: Samstag 30. Juni 2012, 17:26
von Nobuddy
@BlackJack, sorry ... habe bisher noch keine Lösung gefunden, um 'shell=True' wegzulassen. :?
Ich habe es schon mit 'subprocess.check_call' und 'subprocess.check_output' versucht, leider aber ohne Erfolg soweit eins von beiden der richtige Ersatz sein sollte.
Könnte da noch einen etwas genaueren Tipp benötigen. :wink:

@Dav1d, Danke für dies Info, das war mir so nicht klar, ich werde dies versuchen mit einfließen zu lassen.
Daß man nur Pakete aus /etc/sources.list mit apt-get installieren kann ist ja völlig in Ordnung, denn Frempakete sind Sache des Benutzers bzw. des Admin.

Ich habe jetzt mal die Dinge versucht einfließen zu lassen, die mir klar waren und habe Funktionen eingesetzt.
Hier mal das Konstrukt (leider noch mit 'shell=True'):

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys, subprocess, imp


DATEI = 'gui_start.py'
MODUL = DATEI.split('.')[0]

APT_GET = 'sudo apt-get install -y'
APTITUDE = 'sudo aptitude install -y'

COMMAND_QUESTION = '''Welchen Befehl möchten Sie für die
Installation von Paketen verwenden?
1: %s
2: %s'''

IMPORT_INFO = '''Das Paket %s wird für das Starten
des Python-Modul %s benötigt.
Das Paket %s ist nicht installiert ist!

Soll das Paket %s jetzt installiert werden?'''


INSTALL = False
def command():
    global INSTALL
    counter = 0
    while INSTALL == False:
        print COMMAND_QUESTION % (APT_GET.split(None, 2)[1], APTITUDE.split(None, 2)[1])
        number = raw_input('Nummer: ')
        counter += 1
        if number == '1':
            INSTALL = APT_GET
        elif number == '2':
            INSTALL = APTITUDE
        else:
            if counter <= 3:
                print 'Nummer %s existiert nicht!' % number
                print ''
            else:
                print 'Eingabefehler, Abbruch!'
                sys.exit()


def modul_control():
    try:
        imp.load_source(MODUL, DATEI)
    except ImportError, e:
        if 'please install the' in str(e):
            paket = e.message.rsplit(None, 2)[1]
            if paket:
                print IMPORT_INFO % (paket, DATEI, paket, paket)

                answer = raw_input('< ja / nein >: ')

                if answer == 'ja':
                    print ''
                    print 'Geben Sie Ihr Passwort ein!'
                    subprocess.call('%s %s' % (INSTALL, paket.lstrip('-')), shell=True)
                elif answer == 'nein':
                    print''
                    print 'Installation von %s wurde abgebrochen!' % paket
                else:
                    print ''
                    print 'Fehlerhafte Eingabe, Installation von %s wurde abgebrochen!' % paket
                    sys.exit(1)
    except BaseException, e:
        print e


def modul_check():
    try:
        imp.load_source(MODUL, DATEI)
        print 'Alles ok!'
        sys.exit()
    except:
        if INSTALL == False:
            command()
            print ''
            print 'Sie haben %s gewählt!' % INSTALL.split(None, 2)[1]
            print ''
        modul_control()

if __name__ == "__main__":
    modul_check()

Re: Modul zum Nachinstallieren fehlender Pythonpakete

Verfasst: Samstag 30. Juni 2012, 17:39
von Nobuddy
Mit 'shell=False', sieht das so aus:

Code: Alles auswählen

Welchen Befehl möchten Sie für die
Installation von Paketen verwenden?
1: apt-get
2: aptitude
Nummer: 1

Sie haben apt-get gewählt!

Das Paket python-tk wird für das Starten
des Python-Modul gui_start.py benötigt.
Das Paket python-tk ist nicht installiert ist!

Soll das Paket python-tk jetzt installiert werden?
< ja / nein >: ja

Geben Sie Ihr Passwort ein!
Traceback (most recent call last):
  File "modul_control.py", line 87, in <module>
    modul_check()
  File "modul_control.py", line 83, in modul_check
    modul_control()
  File "modul_control.py", line 60, in modul_control
    subprocess.call('%s %s' % (INSTALL, paket.lstrip('-')), shell=False)
  File "/usr/lib/python2.7/subprocess.py", line 493, in call
    return Popen(*popenargs, **kwargs).wait()
  File "/usr/lib/python2.7/subprocess.py", line 679, in __init__
    errread, errwrite)
  File "/usr/lib/python2.7/subprocess.py", line 1249, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory

Re: Modul zum Nachinstallieren fehlender Pythonpakete

Verfasst: Samstag 30. Juni 2012, 18:01
von Nobuddy
Ich habe jetzt die Lösung für 'shell=False' gefunden! :D

Code: Alles auswählen

                    command_line = '%s %s' % (INSTALL, paket.lstrip('-'))
                    args = shlex.split(command_line)
                    print ''
                    print 'Geben Sie Ihr Passwort ein!'
                    subprocess.call(args, shell=False)
Ich hoffe, daß dies so ok ist, aber vielleicht gibt es auch noch eine bessere Alternative ...?

Re: Modul zum Nachinstallieren fehlender Pythonpakete

Verfasst: Samstag 30. Juni 2012, 18:15
von EyDu
Nobuddy hat geschrieben:Ich hoffe, daß dies so ok ist, aber vielleicht gibt es auch noch eine bessere Alternative ...?
Die beste Lösung wäre es, wenn du dir die Dokumentation zum subprocess-Modul durchliest und ensprechend anwendest ;-)

Re: Modul zum Nachinstallieren fehlender Pythonpakete

Verfasst: Sonntag 1. Juli 2012, 02:37
von Leonidas
Und du weißt schon, das deine ganze Lösung für höchstens 3 Pakete funktioniert, weil vermutlich andere Sachen wie numpy oder so keine Fehlermeldungen haben in denen die Paketnamen erwähnt sind?

Re: Modul zum Nachinstallieren fehlender Pythonpakete

Verfasst: Sonntag 1. Juli 2012, 10:34
von Dav1d
@Leonidas, dann wählt man als Paketmanager eben PIP 8)

Re: Modul zum Nachinstallieren fehlender Pythonpakete

Verfasst: Sonntag 1. Juli 2012, 13:21
von Leonidas
Projektnamen und Paket/Modulnamen müssen nicht unbedingt übereinstimmen...

Re: Modul zum Nachinstallieren fehlender Pythonpakete

Verfasst: Sonntag 1. Juli 2012, 15:59
von Nobuddy
Hallo zusammen,

@EyDu, mein Problem ist die englische Sprache ... und momentan keinen Englischtranslater, der Web-Seiten übersetzt.
Daher ist dies für mich eine echte Herausforderung ...

@Leonidas, unter Ubuntu gibt es das Paket python-numpy, das bei mir schon installiert ist. Ob keine Fehlermeldung kommt, wenn in einem Modul numpy benötigt wird aber nicht installiert ist, das müßte man testen.
Ob mehr als 3 Pakete zum Installieren durchlaufen, müßte ich testen.
Was ich aber noch in mein Modul einbauen muß, ist ein Update auf apt-get bzw. aptitude, damit wenn zwei aufeinander folgende Module das gleiche Paket benötigen, nicht ein zweites mal zur Installation angeboten wird.

@Dav1d, PIP kenne ich jetzt noch nicht, aber vielleicht kannst Du mir dazu ein paar Tipps geben?

In der Zwischenzeit habe ich an dem Projekt weitergemacht.
Ich lese jetzt die Dateien eines Ordners ein und filtere nur die py-Dateien heraus.
Bei ImportError werden nicht installierte Pakete zur Installation angeboten.
Alle anderen Errorś werden per print-Anweisung ausgegeben, diese könnte man auch in eine LOG-Datei schreiben.

modul_control.py: https://gist.github.com/3028598#file_modul_controll.py

Ausgabe mit Installation eines paketes: https://gist.github.com/3028598#file_au ... stallation

Ausgabe Modulcheck: https://gist.github.com/3028598#file_paketcheck

Bestimmt sind da noch Fehler drin, daher würde ich mich freuen, wenn Ihr mir helfen würdet diese zu beseitigen! :wink:

Wenn Ihr die Ausgaben anschaut, werden Euch die Ausgaben anderer Module auffallen, die hier eigentlich nichts verloren haben. Da fehlt mir noch eine Idee, wie ich das ausblenden kann.
Auch werdet Ihr solche Ausgaben in der Art sehen
('ex: ', 'gui_start.py', NameError("global name 'psutil' is not defined",))
Keine Ahnung warum dies ausgegeben wird. psutil wird in den Modulen nicht importiert und auch nicht verwendet. Vielleicht fällt Euch etwas ein dazu?
Kann mir nur vorstellen, daß wenn ein bestimmtes Modul bei dem psutil verwendet wird, in anderen Modulen importiert wird, daß dies dazu führt.