CMD-Befehl / .bat wird über subprocess.Popen anders als manuell ausgeführt

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.
Antworten
ME33389
User
Beiträge: 4
Registriert: Montag 25. Mai 2020, 09:55

Hallo,

ich möchte PTC Creo (CAD-System) zusammen mit einer Trail-file (Befehle, was Creo machen soll) von einen Python Skript öffnen.

Den Befehl zum öffnen (.exe,.psf (Lizenz) und .txt(Trail-file)) habe ich in eine .bat geschrieben. Wenn ich diese vom Explorer aus öffne wird Creo gestartet und führt die Trail-file aus (genau das will ich von Python aus machen).
Wenn ich jedoch dieselbe .bat von Python per subprocess.Popen öffne, startet Creo zwar mit Lizenz ignoriert jedoch die Trail-file ohne Fehlermeldung.

Ich nutze Windows 10, Python 3.6.10, Creo 4.0

Hier mein Code:

bat-file:
"C:\Program Files\ptc\Creo 4.0\M070\Parametric\bin\parametric.exe" "C:\Program Files\ptc\Creo 4.0\M070\Parametric\bin\parametric1.psf" M:\python_trail_test\Standard_trail_wo_HSCB.txt

Python:
Import os
Import subprocess
subprocess.Popen(r"M:\python_trail_test\Creo_bat.bat")

Ich habe auch schon versucht die drei Dateien/Dateipfade (exe, psf, txt) in Popen als einzelne Argumente anzugeben, mit demselben Ergebnis.
Meiner Meinung nach sollte es keinen Unterschied machen, ob ich die .bat-Datei von Python oder per Doppelklick aus dem Explorer öffne, irgendwie das das aber der Fall.
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@ME33389: Auch wenn die Pfade alle absolut sind: Könnte es sein, dass sich die beiden Varianten durch das aktuelle Arbeitsverzeichnis unterscheiden und dass das wichtig ist?
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
ME33389
User
Beiträge: 4
Registriert: Montag 25. Mai 2020, 09:55

Hallo __blackjack__,

danke für den Vorschlag, ich habe eben folgendes ausprobiert:
Jeweils erst in das Verzeichnis, in dem die .bat Datei liegt gegangen, und dann diese aufgerufen. Das müsste dann jeweils das gleiche Arbeitsverzeichnis sein.

in CMD:
cd "M:\python_trail_test"
"M:\python_trail_test\Creo_bat.bat"

=> Creo wird gestartet & Trail-file ausgeführt

in Python:
Import os
Import subprocess
os.chdir(pathlib.Path(r"M:\python_trail_test"))
test = subprocess.Popen(r"M:\python_trail_test\Creo_bat.bat")

=> es wird nur Creo gestartet, zwar mit Lizenz, aber ohne Trail-file.


Interessant ist, dass Python den Befehl, der in der .bat steht, in seinem Terminal aufschlüsselt:

(py36) M:\python_trail_test>"C:\Program Files\ptc\Creo 4.0\M070\Parametric\bin\parametric.exe" "C:\Program Files\ptc\Creo 4.0\M070\Parametric\bin\parametric1.psf" "M:\python_trail_test\Standard_trail_wo_HSCB.txt"

Meine Idee war auch schon, dass ich das in einer weiteren .bat verschachtele. Ergebnis ist gleich, nur dass die verschachtelte .bat in der Ausgabe angezeigt wird.


Gibt es vllt. noch irgendeinen Parameter, den man Popen mitgeben muss, damit es den CMD-Befehl wirklich gleich ausführt?
Benutzeravatar
DeaD_EyE
User
Beiträge: 1240
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Probier das mal ohne Batch-Datei.

Code: Alles auswählen

from pathlib import Path
from subprocess import Popen


CREO_PATH = r"C:\Program Files\ptc\Creo 4.0\M070\Parametric\bin"
CREO_BIN = "parametric.exe"

def start_creo(psf, trail):
    cmd = [
        str(CREO_PATH / CREO_BIN),
        str(CREO_PATH / psf),
        str(trail)
    ]
    return Popen(cmd)


if __name__ == "__main__":
    psf = r"parametric1.psf"
    trail = r"M:\python_trail_test\Standard_trail_wo_HSCB.txt"
    proc = start_creo(psf, trail)
 
Wenn man die Path-Objekte verwendet, muss man im Hinterkopf behalten, dass es keine Strings sind. Übergibt man z.B. die Path-Objekte einer Liste, die dann von Popen als parameter an den Prozess übergeben werden sollen, so müssen diese zuvor in str konvertiert werden. Seit irgendeiner Version darf das erste Argument auch ein Path objekt sein. Die weiteren Argumente müssen aber weiterhin str sein.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
ME33389
User
Beiträge: 4
Registriert: Montag 25. Mai 2020, 09:55

Hallo DeaD_EyE,

das scheint keinen Unterschied zu machen, ob ich die drei Dateien in der .bat angebe, oder direkt in Python als Liste oder kompletter String (siehe unten).
In beiden Fällen wird die letzte Datei leider ignoriert.

Code: Alles auswählen

os.chdir(pathlib.Path(r"C:\Program Files\ptc\Creo 4.0\M070\Parametric\bin"))
test = subprocess.Popen("parametric.exe parametric1.psf 'M:\python_trail_test\Standard_trail_wo_HSCB.txt'")
Hab das ganze (ein String, Liste) auch mit subprocess.call und subprocess.run probiert. Os.system habe ich mit dem kompletten String getestet, eine Liste akzeptiert das ja nicht.
Benutzeravatar
DeaD_EyE
User
Beiträge: 1240
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Ich habe das Programm nicht, deswegen musst du wohl testen.
Bei einer Software, die 3.110 € kostet, könnte man auch mal die Unterstützung in Anspruch nehmen.

Code: Alles auswählen

"parametric.exe parametric1.psf 'M:\python_trail_test\Standard_trail_wo_HSCB.txt'"
Unter Windows scheint das einfach zu funktionieren. Unter Linux jedenfalls nicht.
Die Single-Quotes sind wahrscheinlich ein Teil des Problems. Die werden so an dein Programm übergeben.

Code: Alles auswählen

subprocess.Popen("cmd.exe /c echo '123'")
'123'

Code: Alles auswählen

subprocess.Popen("cmd.exe /c echo 123")
123
Oder besser als eigene Argumente:

Code: Alles auswählen

subprocess.Popen(["cmd.exe", "/c", "echo", "123"])
123
Bitte dazu einmal in die Dokumentation schauen: https://docs.python.org/3/library/subpr ... onstructor
An example of passing some arguments to an external program as a sequence is:

Code: Alles auswählen

Popen(["/usr/bin/git", "commit", "-m", "Fixes a bug."])
Möglicherweise braucht das Programm ein anderes Arbeitsverzeichnis (current working directory), dass du bei der Verknüpfung kontrollieren solltest.
Umgebungsvariablen können das eigentlich nicht die Ursache sein, da die aktuelle Umgebung auch dem Prozess zur Verfügung steht.
Kontrolliere einfach mal, ob das Programm noch zusätzliche Umgebungsvariablen erstellt hat.

Mach auch mal den Test, ob die Datei überhaupt existiert:

Code: Alles auswählen

import pathlib
pathlib.Path(r"M:\python_trail_test\Standard_trail_wo_HSCB.txt").exists()
Wenn die Datei existiert, liefert er ein True zurück.

Noch etwas zu den Backslahses, dass aber aktuell nicht Teil deines Problems ist:
Die Backslash können auch noch ein Problem darstellen, da sie in Kombination mit anderen Zeichen Steuerzeichen repräsentieren.
In deinem Fall würde es aber nicht zutreffen, da \p und \S keine Ersetzung haben.

Ersetzt werden z.B. diese Sequenzen:
\n == Newline
\r == Carriage Return
\b == Bell

Das r vor den Anführungszeichen deaktiviert das Escaping: https://docs.python.org/3/reference/lex ... s-literals
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
ME33389
User
Beiträge: 4
Registriert: Montag 25. Mai 2020, 09:55

Habe eben den Fehler gefunden, nachdem ich das Thema in der PTC community geposted habe.
Ich muss zugeben, dass ich nicht geschrieben habe, wie ich die .py Datei ausführe, das ist nämlich der Unterschied.

Trotzdem nochmal Danke für eure Unterstützung!

Zum coden nutze ich Visual Studio Code mit der python Extension und miniconda.
VS Code hat super viele Funktionen um das Programmieren zu vereinfachen, unter anderem den eingebauten Terminal.

Leider führt der VS Code terminal (Einstellung python!) den Code anders aus, als das Anaconda Prompt (mit "python.exe pfad/Skript.py").
Was im Detail dort anders ist, weiß ich nicht.
Antworten