Seite 1 von 1

python perl subprocess subprocess.Popen

Verfasst: Donnerstag 22. August 2013, 13:12
von pystartup
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()

Re: python perl subprocess subprocess.Popen

Verfasst: Donnerstag 22. August 2013, 13:49
von 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.

Re: python perl subprocess subprocess.Popen

Verfasst: Donnerstag 22. August 2013, 21:12
von pystartup
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

Re: python perl subprocess subprocess.Popen

Verfasst: Donnerstag 22. August 2013, 21:23
von 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.

Re: python perl subprocess subprocess.Popen

Verfasst: Donnerstag 22. August 2013, 21:29
von Sirius3
@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.

Re: python perl subprocess subprocess.Popen

Verfasst: Freitag 23. August 2013, 08:19
von pystartup
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 :) )

Re: python perl subprocess subprocess.Popen

Verfasst: Freitag 23. August 2013, 09:19
von Sirius3
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]

Re: python perl subprocess subprocess.Popen

Verfasst: Freitag 23. August 2013, 09:21
von 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.

Re: python perl subprocess subprocess.Popen

Verfasst: Montag 26. August 2013, 14:38
von pystartup
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 ...

Re: python perl subprocess subprocess.Popen

Verfasst: Mittwoch 28. August 2013, 10:54
von pystartup
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? :?

Re: python perl subprocess subprocess.Popen

Verfasst: Mittwoch 28. August 2013, 11:00
von cofi
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)

Re: python perl subprocess subprocess.Popen

Verfasst: Mittwoch 28. August 2013, 11:37
von pystartup
DANKE DANKE DANKE DANKE DANKE DANKE!!!! :D

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

Vielen Dank!