2016-06-13 14 views
2

Nach vielen Recherchen im Internet, zu vielen verschiedenen Themen, war ich nicht in der Lage, die Lösung meines Problems zu finden.Python externe Projektskriptausführung

Ich entwickle ein Tool (mit grafischer Oberfläche), das die Verarbeitung von Python-Skripten aus verschiedenen Projekten ermöglicht. Um keine Abhängigkeiten zu haben, bitte ich den Benutzer, sowohl das Projektverzeichnis als auch das zu verarbeitende Skript anzusprechen.

Um dieses Werkzeug zu entwickeln, habe ich in meiner IDE ein Projekt "benchmark_tool", welches das Projekt ist, das die GUI integriert, und das Projekt "test_project", das verschiedene Testskripte gruppiert. Offensichtlich ist das endgültige Ziel das zu kompilierende Werkzeug und somit verschwindet das Projekt "benchmark_tool" aus der IDE. Hier

ist die IDE-Architektur:

benchmark_tool (python project) 
    __init__.py 
    main.py 

test_project (python project) 
    __init__.py 
    module1 
     __init__.py 
     test_script.py 
    module2 
     __init__.py 
     imports.py 

Wie es funktioniert: Die main.py soll nennen test_script.py. test_script.py ruft imports.py beim ersten Start des Skripts auf.

UPDATE

habe ich versucht, einige Änderungen in meinem Haupt-Code:

import sys 
import subprocess 

subprocess.check_call([sys.executable, '-m', 'test_project.module1.test_script'], cwd='D:/project/python') 

I

Traceback(most recent call last): 
    File "C:/Python31/lib/runpy.py", line 110, in run module as main 
     mod_name, loader, code, fname = _get_module_detail(mod_name) 
    File "C:/Python31/lib/runpy.py", line 91, in get module details 
     code = loader.get_code(mod_name) 
    File "C:/Python31/lib/pkgutil.py", line 272, in get code 
     self.code = compile(source, self.filename, 'exec') 
    File "D:/project/python/test_project/module1/test_script.py", line 474 


SyntaxError: invalid syntax 
Traceback (most recent call last): 
    File "D:/other_project/benchmark_tool/main.py", line 187, in read 
     subprocess.check_call([sys.executable, '-m', 'module1.test_script.py'], cwd='D:/project/python/test_project') 
    File "C:/Python31/lib/subprocess.py", line 446, in check call 
     raise CalledProcessError(retcode, cmd) 
subprocess.CalledProcessError: Command '['C:/Python31/python.exe', '-m', 'module1.test_script.py']' returned non-zero exit status 1 

Hinweis diesen Fehler habe funktioniert es mit subprocess.Popen(['python','D:/project/python/test_project/module1/test_script.py])

Was ist der Hauptunterschied zwischen beiden Methoden? Ich muss auch Argumente an test_scripts.py übergeben, welches ist das beste, um mit einem Python-Skript zu kommunizieren (Eingabe- und Ausgabedaten werden ausgetauscht)?

Dank durch Voraus

+0

auf Ihrem Update: Verstehen Sie, dass '' module1.test_script' und module1/test_script .py' sind verschiedene Zeichenfolgen? Ändere 'PYTHONPATH' nicht. Wo siehst du, dass ich den Pythonpfad in meiner Antwort verändere? Bitte lesen Sie meine Antwort sorgfältig - fügen Sie keinen anderen Code hinzu. Zur Klarstellung aktualisieren Sie Ihre Frage und geben Sie an, ob module1 und module2 Python-Module auf oberster Ebene sind oder ob es sich um Submodule von 'test_project' handelt (d. H. Ob 'test_project' ein Python-Modul oder nur ein Verzeichnis ist). Abhängig von der Antwort verwenden Sie das entsprechende Codebeispiel aus meiner Antwort, das beide Fälle abdeckt. – jfs

+0

Tut mir leid, ich habe 'module1.test_script' geschrieben, aber ich habe es nicht gut geschrieben (Ich kann meinen Code nicht kopieren/einfügen, ich muss es schreiben). test_project ist ein Python-Modul, nicht nur ein Verzeichnis, und module1 und module2 sind Submodule von test_script. Ich habe den Befehl 'PYTHONPATH' entfernt, aber den gleichen Fehler bekommen. –

+0

Warum musst du es schreiben? Wenn Sie nicht wissen, wie Sie von der Befehlszeile kopieren und einfügen können, lernen Sie (es ist nützlich) - stellen Sie eine separate Frage zu Ihrer spezifischen Umgebung. Ich kann dir nicht helfen, wenn du nicht den genauen Befehl gibst. Auch hier unterscheidet sich "module1.test_script.py" von "module1.test_script". Wenn 'test_project' ein Python-Modul ist, dann benutze die zweite Variante aus meiner Antwort:' subprocess.check_call ([sys.executable, '-m', 'test_project.module1.test_script'], cwd = r'D: \ projekt \ python ') '. Nicht verwandt: Sie können Raw-String-Literale für Windows-Pfade verwenden: mit Präfix 'r''. – jfs

Antwort

0

ein „externes Projekt Skript“ ausführen zu können, installieren Sie es zB: pip install project (in einem virtualenv laufen, wenn Sie möchten) und dann das Skript wie bei jeder anderen ausführbaren Datei ausführen:

#!/usr/bin/env python 
import subprocess 

subprocess.check_call(['executable', 'arg 1', '2']) 

Wenn Sie nicht möchten, dass das Projekt installieren und es hat keine Abhängigkeiten (oder Sie annehmen, dass sie bereits installiert sind), dann ein Skript aus einem bestimmten Pfad als Subprozess laufen (vorausgesetzt, es ist module1/__init__.py-Datei) :

#!/usr/bin/env python 
import subprocess 
import sys 

subprocess.check_call([sys.executable, '-m', 'module1.test_script'], 
         cwd='/abs/path/to/test_project') 

Mit -m, um das Skript auszuführen, vermeidet many import issues.

Das obige geht davon aus, dass test_project kein Python-Paket ist (keine test_project/__init__.py). Wenn test_project selbst ist ein Python-Paket enthält sie dann in dem Modulnamen und starten Sie aus dem übergeordneten Verzeichnis statt:

subprocess.check_call([sys.executable, '-m', 'test_project.module1.test_script'], 
         cwd='/abs/path/to') 

Sie den Pfad zu test_project Verzeichnis als Befehlszeilenparameter übergeben konnte (sys.argv) oder lesen sie aus eine Konfigurationsdatei (configparser, json).Vermeiden Sie die Berechnung relativ zum Installationspfad des übergeordneten Skripts (wenn Sie dann pkgutil, setuptools 'pkg_resources verwenden müssen, um die Daten zu erhalten). Um einen Speicherort für Benutzerdaten zu finden, können Sie appdirs Python package verwenden.

+0

Ich verstehe nicht, warum muss ich das Projekt installieren? –

+0

@v_lfr Wie werden die Abhängigkeiten des Projekts auf Ihrem Computer angezeigt? – jfs

+0

Eigentlich habe ich 2 Projekte. Eines wird ein kompiliertes Tool sein, das die Benutzer auffordert, andere Python-Projekt-Links mit Testskripten zur Ausführung zu verbinden. Also werde ich 1 kompiliertes Projekt mit vielen Python-Projekten haben, die bereits auf Computern von Benutzern sein werden. Entsprechende Projektabhängigkeiten werden automatisch zu "PYTHONPATH" hinzugefügt, wenn der Benutzer den Projektlink einfügt. Hoffe, ich bin verständlich ... @ J.F.Sebastian –

0

Es gibt 3 Probleme, die ich sehe, dass Sie zu beheben haben:

  1. Um von module2 zu importieren, müssen Sie das Verzeichnis in ein Paket machen, indem eine leere *__init__.py Datei darin platzieren
  2. Wenn Ausführen test_script.py, Sie müssen den vollständigen Pfad zu der Datei, nicht nur Dateiname
  3. Fixing sys.path nur für Ihr Skript arbeiten. Falls Sie Fragen zu test_script.py, setzen Sie die Umgebungsvariable PYTHONPATH

daher propagieren wollen, meine Lösung ist:

import os 
import sys 
import subprocess 

# Here is one way to determine test_project 
# You might want to do it differently 
script_dir = os.path.abspath(os.path.dirname(__file__)) 
test_project = os.path.normpath(os.path.join(script_dir, '..', 'test_project')) 

python_path = '{}:{}'.format(os.environ.get('PYTHONPATH', ''), test_project) 
python_path = python_path.lstrip(':') # In case PYTHONPATH was not set 

# Need to determine the full path to the script 
script = os.path.join(test_project, 'module1', 'test_script.py') 
proc = subprocess.Popen(['python', script], env=dict(PYTHONPATH=python_path)) 
+0

1. Ich habe es nicht erwähnt, aber ich habe eigentlich bereits eine init.py in meinem Modul2. 2. Ich habe auch versucht, den vollständigen Pfad zu setzen, aber es hat trotzdem nicht funktioniert. 3.Wenn ich recht habe, ist das Setzen der Umgebungsvariable PYTHONPATH identisch mit 'sys.path.append (test_project)'? Ich habe Ihre Lösung versucht, aber es hat nicht funktioniert, ich habe immer noch den gleichen Fehler @HaiVu –

+0

Für # 2, funktioniert ** nicht ** bedeuten Skript nicht gefunden, oder nicht importieren können? Für # 3 ist 'sys.path.append (...)' nicht dasselbe wie das Einrichten von PYTHONPATH, das habe ich in meinem Skript getestet und bestätigt. –

+0

Es gibt mindestens zwei Probleme: 1- Wie installiert es 'test_project' Abhängigkeiten? 2. Es führt ein Skript von * innerhalb * eines Python-Pakets direkt aus (was Sie nicht tun sollten). Wenn eine Person PYTHONPATH nicht selbst konfigurieren kann, wäre es schwierig, [die Importprobleme] zu lösen (https://www.python.org/dev/peps/pep-0395/#traps-for-the-unwary). die entstehen auch. Nicht verwandt: Sie könnten 'os.pathsep' und [' get_script_dir() '] (http://stackoverflow.com/a/22881871/4279) verwenden (obwohl das Suchen nach Dateien relativ zu Ihrem Installationsverzeichnis nicht gut aussieht - vielleicht , 'appdirs' kann geeignetere Pfade bereitstellen). – jfs