2015-03-31 4 views
7

Gibt es eine Möglichkeit, python/pip zu ändern, wenn ein Import fehlschlägt zur Laufzeit, es würde versuchen, das Modul (mit dem gleichen Namen) von pip zu installieren und dann das Modul importieren?Ändern Sie Python/PIP, um Module automatisch zu installieren, wenn der Import fehlschlug

Ich würde sagen, es wäre als ein schöner Standard sein, nur einen Fehler aus. Wenn nach dem Modul von pip Problemen Laden passieren, dann wäre es auch einen Fehler aus, ähnlich wie wenn ich merke ich etwas nicht importieren kann, versuchen pip install und kommt dann auf die gleiche genaue Fehlermeldung.

Ich weiß, wir requirements.txt zum Bündeln ein Paket verwenden können, aber ich spreche von einem „Client“ (Person, die das Skript ausgeführt wird) eher als „Anbieter“ (Person, welche die Schrift) Perspektive; das heißt, ich möchte als Client ein beliebiges Skript importieren und Abhängigkeiten automatisch lösen lassen.

Ich verstehe, dass dies möglicherweise Probleme verursachen könnte, aber jedes Mal, wenn ich einen ImportError sehe, würde ich einfach versuchen, das Modul pip install trotzdem. Nur wenn das Modul nach der Pip-Installation nicht funktionieren würde, "würde ich weitere Fragen stellen".

Ich dachte an so etwas wie dieser Schnipsel, die mit dem Python-Prozess werden „eingebaut“ würden:

def getDirectoryOfInterpreter(p): 
    return "someway to return the directory" 

try: 
    import somemodule 
except ImportError: 
    os.system(getDirectoryOfInterpreter('THIS_INTERPRETER_BINARY') + ' pip install ' + "MODULE_NAME") 
    import somemodule 
+0

Ja. Das wird in Python-Paketen gemacht, wenn sie installiert werden, prüfen sie die Abhängigkeiten und installieren den Rest der Pakete. –

+0

Ich spreche über die Abhängigkeiten zur Laufzeit eines Skripts zu lösen. – PascalVKooten

+0

Ich habe vielleicht einen Weg, um Ihnen zu helfen, aber die Abhängigkeit sollte installiert werden, bevor –

Antwort

11

Sie können dies mit pipimport tun, wenn virtualenv verwenden. Es funktioniert wahrscheinlich mit dem System Python, wenn Sie entsprechende Rechte haben, um die notwendigen Verzeichnisse zu schreiben (mindestens site-packages, aber Ihr Import könnte einen Befehl haben, der pip versucht, irgendwo in den PATH zu setzen). Da es ratsam ist, virtualenvs immer für die eigene Entwicklung zu verwenden, habe ich nie versucht, pipimport mit dem System Python zu verwenden.

Sie müssen pipimport in Ihre virtualenv von Hand importieren:

virtualenv venv 
source venv/bin/activate 
pip install pipimport 

Erstellen Sie dann eine Datei autopipimport.py, die Sie zuerst in jedem Modul zu importieren:

# import and install pipimport 
import pipimport 
pipimport.install() 

nun in jeder anderen .py Datei können Sie do:

import autopipimport 
import some.package.installable.by.pip 

Ich einmal versucht (Auto von Neugier) die beiden pipimport bezogenen Linien venv/lib/python2.7/site.py zu werden automatisch „geladen“, aber das war zu früh in der Kette hinzuzufügen und hat nicht funktioniert.

pipimport nur versuchen pip zu verwenden, um ein bestimmtes Modul einmal installiert werden, Informationen über die Speicherung, was in einer .pipimport-ignore Datei versucht worden (sollte unter venv sein, es sei denn, dass nicht beschreibbar ist).

+2

Beachten Sie, dass dies erfordert, dass der Paketname mit dem Projektnamen auf PyPI übereinstimmt; 'von bs4 import BeautifulSoup' wird das 'beautifulsoup4'-Projekt, bei dem es registriert ist, nicht finden. –

+0

Obwohl allgemein zutreffend, basiert die Übereinstimmung auf der Frage des OP darauf, dass die Übereinstimmung gegeben ist. – Anthon

+0

@MartijnPieters Genau das hatte ich auch im Sinn, obwohl es eher eine Ausnahme ist. Kannst du an einen anderen denken? So oder so, das Ziel ist nicht, sich darauf zu verlassen, keine Fehler zu haben, aber Sie würden nur eine Menge davon reduzieren. – PascalVKooten

0

Hier ist etwas, das ich für meine eigene Neugier getan haben.

Ja, das unsafely ruft eine Shell im Hintergrund mit beliebiger Benutzereingabe eine nicht bevorzugte Funktion. Bitte verwenden Sie diesen Code nicht für die Produktion.

import os 

Libraries_Installed = False 

def Pip_Install(library): 
    """Locate pip.exe on system and install library. 
    Be sure to sanitize input to prevent RCE.""" 
    global Lib_Installed 

    if os.path.isfile('C:\\Python27\\Scripts\\pip.exe'): 
     print '[!] c:\Python27\Scripts\pip.exe => pip' 
     stream = os.popen('C:\Python27\Scripts\pip.exe install %s' % library) 
     Result = stream.read() 

     if 'Successfully installed' in str(Result): 
      print '\n\n[+] Successfully installed %s' % library 
      Lib_Installed = True 

     elif 'FAIL' in str(Result).upper() or 'FAILED' in str(Result).upper() \ 
     or 'FAILURE' in str(Result).upper(): 
      print '[!] Unable to install %d' % library 
      print '[!] Please manually run the pip installer' 
      print '[!] try: C:\Python27\Scripts\pip.exe install %s' % library 

    elif os.path.isfile('D:\\Python27\\Scripts\\pip.exe'): 
     stream = os.popen('D:\Python27\Scripts\pip.exe install %s' % library) 
     Result = stream.read() 

     if 'Successfully installed' in str(Result): 
      print '\n\n[+] Successfully installed %s' % library 
      Lib_Installed = True 

     elif 'FAIL' in str(Result).upper() or 'FAILED' in str(Result).upper() \ 
     or 'FAILURE' in str(Result).upper(): 
      print '[!] Unable to install %d' % library 
      print '[!] Please manually run the pip installer' 
      print '[!] try: C:\Python27\Scripts\pip.exe install %s' % library 

# Python library that may need to be installed 
try: 
    import Tkinter 
    import tkFileDialog 
except: 
    print '[!] Error importing Tkinter ... Trying pip installer' 
    Pip_Install('tkinter') 

if Lib_Installed == True: 
    print '\n[!] The following Python libraries were installed automatically:' 
    for library in Libs: 
     print str(library) 
    Q = raw_input('''\n[!] Please exit the program and run a new instance. 
[!] Enter [Y] to continue anyways''') 
    if Q.upper()[0] == 'Y': 
     pass 
    else: 
     exit() 
+1

Ja, das ruft unsicher eine Shell im Hintergrund mit beliebigen Benutzereingaben auf, die eine nicht bevorzugte Funktion verwenden. Bitte verwenden Sie diesen Code nicht für die Produktion. – Injectnique

Verwandte Themen