python perl subprocess subprocess.Popen

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
pystartup
User
Beiträge: 6
Registriert: Donnerstag 22. August 2013, 12:20

Hallo Forum User,

mein erster POST, meine erste Frage :)

Vorab, ich bin neu auf dem Gebiet!

Ich habe eine CSV-Datei(benutzer.csv) die ich mit Python einlesen möchte, was auch klappt. Im Code unten ist eine auskommentierte Zeile die das ausgibt was in der Datei steht.

Ich muss allerdings ein Perl-Skript verwenden (AddUser.pl) welchem ich 5 variablen übergeben muss. Und das funktioniert irgendwie nicht ... :( Wenn ich die Zeile:

Code: Alles auswählen

pipe = subprocess.Popen(["perl", "./AddUser.pl", stdout=subprocess.PIPE)
ohne die Variablen schreibe, dann bekomme ich keinen Fehler sondern richigerweise eine ausgabe wie in der Shell, ich soll die Argumente mit angeben ...

Hat jemand eine Idee?

Code: Alles auswählen

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

f = open('benutzer.csv', 'rb')
try:
    reader = csv.reader(f)
    for row in reader:
             pipe = subprocess.Popen(["perl", "./AddUser.pl",  -l row[0], -f row[1], -p '123', -e row[2], row[3]], stdout=subprocess.PIPE)
#       print row[0], row[1], row[2], row[3]
             result = pipe.stdout.read()
             print result
finally:
    f.close()
Zuletzt geändert von Anonymous am Donnerstag 22. August 2013, 13:39, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
BlackJack

@pystartup: Du wirst da doch sicher eine Fehlermeldung bekommen. Die bitte in Zukunft 1:1 angeben, damit man im Ernstfall nicht lange überlegen muss. Hier ist es offensichtlich, dass das keine gültige Python-Syntax ist. Das muss eine Liste mit *Zeichenketten* sein, wobei alles was von der Shell als eigenes Argument übergeben würde, auch in dieser Liste ein einzelnes Argument sein muss. ``ps -A -u bj`` wäre zum Beispiel die Liste ``['ps', '-A', '-u', 'bj']``.

Statt auf `row` mit nichtssagenden Indizes zuzugreifen, könnte man die Werte auf passende Namen verteilen. Also zum Beispiel:

Code: Alles auswählen

for login_shell, f_whatever, expire_date, user_name in reader:
    # ...
Die Namen habe ich mir jetzt ausgedacht, da sollte natürlich etwas stehen was zu den Werten passt.

Statt ``try``/``finally`` könnte man die ``with``-Anweisung verwenden.
pystartup
User
Beiträge: 6
Registriert: Donnerstag 22. August 2013, 12:20

Hey, danke für deine Antwort!!!

Ich habe es so gemacht wie du es beschrieben hast (hoffe ich), aber vielleicht immer noch mit Fehlern ?! ... ich bin einfach zu frisch auf dem Gebiet ...

Aber dann kommt immer noch einer Fehler vom Skript "AddUser.pl" von wegen es werden die v_* Variablennamen übergeben und nicht der Inhalt der Variablen. Vielleicht mache ich noch was falsch mit den Anführungszeichen?

Code: Alles auswählen

#!/usr/bin/python
import csv
import subprocess

with open('User.csv', 'rb') as f:
    reader = csv.reader(f)
    for v_nachname, v_vorname, v_email, v_login in reader:
        pipe = subprocess.Popen(['perl', '/.AddUser.pl',  '-l v_nachname', '-f' v_vorname', '-p 123', '-e v_email', 'v_login'], stdout=subprocess.PIPE)
        result = pipe.stdout.read()
        print result
#       print v_nachname, v_vorname, v_email, v_login
BlackJack

@pystartup: Man sieht doch schon an der Syntaxhervorhebung, dass das offensichtlich falsch ist. Du musst wirklich jedes Argument als eigene Zeichenkette übergeben. Und Argument meint hier aus Sicht der Shell und nicht Argumente die semantisch zusammengehören. '-p' ist zum Beispiel ein Argument und '123' ist ein weiteres. Und dann musst Du natürlich auch noch die ' richtig setzen. Also um die literalen Zeichenketten. Und natürlich nicht um Variablennamen, denn dann wird ja nicht der Wert der sich hinter dem Namen verbirgt verwendet, sondern eine Zeichenkette die aus dem Namen selbst besteht.

Was soll denn der `v_`-Präfix bedeuten? Der wirft IMHO mehr Fragen auf, als das er zum Verständnis beiträgt.
Sirius3
User
Beiträge: 18335
Registriert: Sonntag 21. Oktober 2012, 17:20

@pystartup: Du solltest Code wirklich per Copy-Paste hier ins Forum schreiben und nicht noch von Hand etwas ändern.
Alles was in "Anführungszeichen" (oder 'bla') steht, sind Stringkonstanten. Variablen stehen nicht in Anführungszeichen, hast Du ja bei Deinem »print« auch nicht. Außerdem muß jedes Argument ein Eintrag in der Liste sein, "-l" ist ein Argument und »vorname« auch.
Was soll übrigens der Prefix »v_«? V_Macht v_das v_Lesen v_umständlicher, v_bietet v_aber v_sonst v_keinen v_Vorteil.
pystartup
User
Beiträge: 6
Registriert: Donnerstag 22. August 2013, 12:20

Zunächst vielen Dank für die Hilfe!!! :!:
Sirius3 hat geschrieben:@pystartup: Du solltest Code wirklich per Copy-Paste hier ins Forum schreiben und nicht noch von Hand etwas ändern.
Alles was in "Anführungszeichen" (oder 'bla') steht, sind Stringkonstanten. Variablen stehen nicht in Anführungszeichen, hast Du ja bei Deinem »print« auch nicht. Außerdem muß jedes Argument ein Eintrag in der Liste sein, "-l" ist ein Argument und »vorname« auch.
Was soll übrigens der Prefix »v_«? V_Macht v_das v_Lesen v_umständlicher, v_bietet v_aber v_sonst v_keinen v_Vorteil.
v_ soll einfach nur "Variable_" bedeuten, nach dem Unterstrich habe ich geschrieben wofür diese ist ... Wie macht man das jetzt "richtig" ? :oops:

Code: Alles auswählen

#!/usr/bin/python
import csv
import subprocess

with open('User.csv', 'rb') as f:
    reader = csv.reader(f)
    for v_nachname, v_vorname, v_email, v_login in reader:
        pipe = subprocess.Popen(['perl', '/.AddUser.pl',  '-l' v_nachname, '-f' v_vorname, '-p' '123', '-e' v_email, v_login], stdout=subprocess.PIPE)
        result = pipe.stdout.read()
        print result
#       print v_nachname, v_vorname, v_email, v_login

Fehlermeldung: :twisted:

Code: Alles auswählen

    pipe = subprocess.Popen(['perl', '/.AddUser.pl',  '-l' v_nachname, '-f' v_vorname, '-p' '123', '-e' v_email, v_login], stdout=subprocess.PIPE)
                                                                                     ^
SyntaxError: invalid syntax

Und bitte denkt dran, ich lerne es erst gerade, ich ziehmlich neu in diesem Umfeld (werd aber besser :) )
Zuletzt geändert von Anonymous am Freitag 23. August 2013, 09:06, insgesamt 3-mal geändert.
Grund: Fehlermeldung in Code-Tags gesetzt.
Sirius3
User
Beiträge: 18335
Registriert: Sonntag 21. Oktober 2012, 17:20

Das es eine Variable ist, sieht man schon daran, dass alles was kein Keyword ist und mit einem Buchstaben anfängt eine Variable ist.
Du mußt Variablen also nicht noch extra Kennzeichnen.
Zum Syntaxfehler:

Code: Alles auswählen

In [19]: [8 9]
  File "<ipython-input-19-fd6cdd88b4cc>", line 1
    [8 9]
       ^
SyntaxError: invalid syntax


In [20]: [8, 9]
Out[20]: [8, 9]
BlackJack

@pystartup: Das '^' Zeichen zeigt bei Syntaxfehler normalerweise an die Stelle wo der Compiler bemerkt hat, dass etwas nicht stimmen kann. Das ist normalerweise also irgendwo nach dem Fehler, oder anders herum betrachtet, der Fehler liegt irgend wo davor. Schauen wir in einer Python-Shell mal ob er in der Zeile liegt die im Traceback steht (nachdem den verwendeten Namen ein Wert zugewiesen wurde, damit es keinen `NameError` gibt).

Code: Alles auswählen

In [2]: v_nachname, v_vorname, v_email, v_login = 'xxxx'

In [3]: pipe = subprocess.Popen(['perl', '/.AddUser.pl',  '-l' v_nachname, '-f' v_vorname, '-p' '123', '-e' v_email, v_login], stdout=subprocess.PIPE)
  File "<ipython-input-3-354b7ac71e6d>", line 1
    pipe = subprocess.Popen(['perl', '/.AddUser.pl',  '-l' v_nachname, '-f' v_vorname, '-p' '123', '-e' v_email, v_login], stdout=subprocess.PIPE)
                                                                    ^
SyntaxError: invalid syntax
Mal sehen ob man es auf die Liste eingrenzen kann, die als erstes Argument übergeben wird:

Code: Alles auswählen

In [4]: ['perl', '/.AddUser.pl',  '-l' v_nachname, '-f' v_vorname, '-p' '123', '-e' v_email, v_login]
  File "<ipython-input-4-b639d5f5a03c>", line 1
    ['perl', '/.AddUser.pl',  '-l' v_nachname, '-f' v_vorname, '-p' '123', '-e' v_email, v_login]
                                            ^
SyntaxError: invalid syntax
Ja, da scheint ein Fehler drin zu sein. Also die einzelnen Audrücke testen, welche die einzelnen Elemente der Liste stellen:

Code: Alles auswählen

In [5]: 'perl'
Out[5]: 'perl'

In [6]: '/.AddUser.pl'
Out[6]: '/.AddUser.pl'

In [7]: '-l' v_nachname
  File "<ipython-input-7-a3a3952e3000>", line 1
    '-l' v_nachname
                  ^
SyntaxError: invalid syntax
Da haben wir es: Der Compiler hat keine Ahnung was er mit einer literalen Zeichenkette direkt gefolgt von einem Namen machen soll. Was sollte das denn auch bedeuten, also welches Ergebnis würdest Du von diesem Ausdruck erwarten? Es sollen ja zwei einzelne Elemente der Liste sein. Und Listenelemente werden in einer literalen Liste durch Kommas getrennt.

Man muss sich hier klar machen, dass der Rechner dumm ist. Der denkt nicht mit, kann sich also nicht denken was gemeint sein könnte. Er kann nur stur einem festen Satz an formalen, präzisen Regeln folgen, sowohl was die Syntax angeht, als auch den Programmablauf.

Zum `v_`: `f`, `reader`, `pipe`, und `result` sind auch Variablen. Das könnte man also so ziemlich überall davor setzen wo man einem Namen einen Wert zuweist. Das ist keine Information die dem Leser wirklich etwas bringt. Und da `v_` auch nichts allgemein bekanntes ist, müsste man es auch noch zusätzlich erklären.
pystartup
User
Beiträge: 6
Registriert: Donnerstag 22. August 2013, 12:20

bitte nicht schimpfen, aber leider komme ich damit nicht klar ... :(


Bei mir funktioniert das immer noch nicht ... Ich hab mir schon extra ein Buch bestellt ... Muss aber warten bis das kommt ...
pystartup
User
Beiträge: 6
Registriert: Donnerstag 22. August 2013, 12:20

na kommt, ist da vielleicht noch jemand der mir dabei helfen kann?

Ich probiere schon alles aus was mir nur einfällt ... Aber ich glaub das liegt auch an meiner Erfahrung ...

Also wenn ich das Perl-Skript ohne nichts aufrufe, bekomme ich eine vernünftige Ausgabe:

Code: Alles auswählen

#!/usr/bin/python
import csv
import subprocess


with open('Benutzer.csv', 'rb') as f:
    reader = csv.reader(f)
    for nachname, vorname, email, login in reader:
        pipe = subprocess.Popen(['perl', './AddUser.pl'], stdout=subprocess.PIPE)
        result = pipe.stdout.read()
        print result
Ausgabe:

Code: Alles auswählen

.AddUser.pl [-f firstname] [-l lastname] [-p password] [-g groupname] [-e email] username
	if you define -g with a valid group name then the user will be added that group

Wenn ich einfach nur die Datei auslese, geht es auch:

Code: Alles auswählen

#!/usr/bin/python
import csv
import subprocess


with open('Benutzer.csv', 'rb') as f:
    reader = csv.reader(f)
    for nachname, vorname, email, login in reader:
       print nachname, vorname, email, login




Hat jemand doch noch vielleicht ein Tipp? :?
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Ich nehm mal das hier her:

Code: Alles auswählen

pipe = subprocess.Popen(['perl', '/.AddUser.pl', '-l' v_nachname, '-f' v_vorname, '-p' '123', '-e' v_email, v_login], stdout=subprocess.PIPE)
                                                                                     ^
SyntaxError: invalid syntax
Das erste Argument fuer `Popen` ist eine _ganz normale Liste_, d.h. _jedes_ Element muss mit einem Komma getrennt werden.
Damit:

Code: Alles auswählen

pipe = subprocess.Popen(['perl', '/.AddUser.pl',  '-l', v_nachname, '-f', v_vorname, '-p', '123', '-e', v_email, v_login], stdout=subprocess.PIPE)
pystartup
User
Beiträge: 6
Registriert: Donnerstag 22. August 2013, 12:20

DANKE DANKE DANKE DANKE DANKE DANKE!!!! :D

jetzt funktioniert es und jetzt verstehe ich auch ... :oops:

Vielen Dank!
Antworten