2016-10-19 2 views
0

Ich zerreiße mein Gehirn hier zu versuchen, eine einfache Funktion mit Python ohne Shell = True und bekomme nicht die Ergebnisse, die ich brauche. Ich benutze Python 2.7 unter Linux.Python Unterprozess Hilfe - Kann nicht Shell = true

Ich habe mehrere Methoden ausprobiert, dies zu tun. Es funktioniert gut, wenn ich Shell verwenden = true etwa so:

import subprocess as s 

var1 = s.call("echo $HOME", shell=True) 

und

import subprocess as s 

var1 = s.check_output("echo $HOME", shell=True) 

beide

/home/myhost

zurückkehren ..., wie es sollte, aber alles andere habe ich versucht, scheitert . In den meisten Fällen scheint es, dass es meine Variable als String statt als Befehl übergibt.

Dies sind die Ergebnisse, die ich mit den verschiedenen Methoden erhalten haben:

import subprocess as s 

print var1 

kehrt

[email protected]:~/Desktop$ python home_test.py 
    File "home_test.py", line 42, in <module> 
    main() 
    File "home_test.py", line 11, in main 
    my_test() 
    File "home_test.py", line 16, in check_auth 
    var1 = s.check_output("echo $HOME") 
    File "/usr/lib/python2.7/subprocess.py", line 567, in check_output 
    process = Popen(stdout=PIPE, *popenargs, **kwargs) 
    File "/usr/lib/python2.7/subprocess.py", line 711, in __init__ 
    errread, errwrite) 
    File "/usr/lib/python2.7/subprocess.py", line 1343, in _execute_child 
    raise child_exception 
OSError: [Errno 2] No such file or directory 

Dann habe ich versucht, dies:

import subprocess as s 

var1 = s.Popen(['echo', '$HOME'], stdout=s.PIPE) 

print var1 

kehrt

[email protected]:~/Desktop$ python home_test.py 
<subprocess.Popen object at 0x7f297ebcbf90> 
[email protected]:~/Desktop$echo: write error: Broken pipe 

Dann folgt aus:

import subprocess as s 

cmd1 = '$HOME' 
var1 = s.Popen(['/bin/echo', cmd1], stdout=s.PIPE) 

print var1 

kehrt

('$Home\n', None) 

und diese

import subprocess as s 

cmd1 = 'HOME' 
var1 = s.Popen(['/bin/echo', cmd1], stdout=s.PIPE) 
print var1 

kehrt

[email protected]:~/Desktop$ python home_test.py 
('Home\n', None) 

einige doc, dass sagte, os zu benutzen ... was auch fehlschlug, was nicht überraschend ist, nachdem herausgefunden wurde, dass dies in 2.6 veraltet war.

import os 

var1 = os.popen('echo $HOME') 
print var1 

kehrt

<open file 'echo $HOME', mode 'r' at 0x7f1c6b26f6f0> 
sh: echo: I/O error 

Dann ist mein letzter Versuch (eigentlich waren es mehr ... aber wir werden es nur auf diese verlassen)

import subprocess as s 

var1= s.Popen(["echo", "$HOME"], stdout=s.PIPE).communicate()[0] 

print var1 

kehrt:

[email protected]:~/Desktop$ python home_test.py 
$HOME 

Kann jemand bitte zeigen m in die richtige Richtung? Ich habe einen ganzen Tag damit verbracht, damit zu spielen und brauche bitte Hilfe. Vielen Dank im Voraus für jegliche Hilfe.

+0

In 'var1 = s.Popen (['echo', '$ HOME'], stdout = s.PIPE)' wird nur das erste Array-Element als Skript behandelt. Nachfolgende Array-Elemente sind Argumente für dieses Skript. –

+0

... übrigens, was ist dein wirklicher Anwendungsfall? Im Allgemeinen ist die Verwendung von 'shell = True' die falsche Sache; Es führt Sicherheits-Bugs ein, wenn es nicht mit ausreichender (wesentlicher!) Vorsicht verwendet wird, und tut nichts, was Sie nicht tun können, indem Sie Ihren Python ausführlicher machen. –

Antwort

1

Es klingt wie Sie wirklich nur den Wert einer Umgebungsvariablen erhalten möchten. os.getenv('HOME') sollte das für Sie tun.

+0

Danke, aber das hat nicht funktioniert, ich habe die Ergebnisse in die Kommentare eingegeben –

+0

Nevermind, ich hatte einen Tippfehler. Das hat auch funktioniert. Danke euch beiden. –

+1

Tangentiale Warnung: In der Regel ist es besser, 'os.environ' ausschließlich zu verwenden und das' getenv'/'putenv' aus Konsistenzgründen zu verbieten. Insbesondere ist es ein Problem, wenn Sie die Umgebung mutieren; Der Aufruf von 'putenv' ändert nicht' os.environ', aber muting 'os.environ' wird auch' putenv' (falls unterstützt). Darüber hinaus sind 'getenv' und' putenv' nicht auf allen Betriebssystemen verfügbar (obwohl es zugegebenermaßen nur seltene UNIX-ähnliche Varianten sind, die AFAICT nicht unterstützen), während 'os.environ' immer unterstützt wird. – ShadowRanger

3

Fangen wir mit der Antwort

 
import os 
home = os.environ['HOME'] 
print(home) 

Jetzt auf Ihre Versuche und Ergebnisse zu starten. Ihr Hauptproblem (neben ein paar zufälligen Fehlern) ist, dass $HOME durch den Wert der Umgebungsvariablen durch die Shell ersetzt wird. Ohne die Shell-Argument Erweiterung $HOME ist nur eine Zeichenfolge und das ist, was Sie bekommen.

+0

Danke, das hat funktioniert. Ich weiß nicht, warum ich nicht daran gedacht habe. Wahrscheinlich, weil ich meinen Kopf an die Wand geschlagen habe und versucht habe, einen Subprozess zu benutzen. –

+1

Ihr Hauptproblem war, dass Sie versucht haben, Shell-Variablen-Erweiterung ohne Verwendung der Shell zu tun :) –

+1

@shellsbelles: In der Regel hat die überwiegende Mehrheit der einfachen Shell-Dienstprogramme besser (oder zumindest niedrigerer Aufwand) Äquivalente in Python. Selbst in den Fällen, in denen das Shell-Hilfsprogramm schneller "unterläuft" (z. B. das Lesen komprimierter Daten aus einer '.gz'-Datei ist oberflächlich schneller), geschieht dies normalerweise nur, weil' subprocess' die Parallelität "kostenlos" (und in ' gzip' Modul Fall, in einigen Versionen ist es, weil sie nicht standardmäßig puffern, "io.BufferedReader" Verpackung würde es beheben); Wenn Sie den entsprechenden Python-Code mit Threads oder parallel verarbeiten, würde er nicht viel verlieren. – ShadowRanger

1

Die Antwort, die os.environ['HOME'] erwähnt, ist richtig, aber es ist wahrscheinlich nicht, was Sie für die Portabilität wollen. Es gibt keine Garantie, dass HOME gesetzt ist (es ist per Konvention, nicht erforderlich; Benutzer könnten es löschen, Shells könnte wählen, es nicht zu setzen, etc.). Und wenn Sie schließlich Portabilität zu Windows wollen, ist das nicht sein Name. Wenn Sie den Home-Verzeichnis des Benutzers mögen, überprüfe die Umwelt nicht direkt, sondern os.path.expanduser verwenden, um intelligentere Home-Verzeichnis-Lookup-Logik zu verwenden:

import os.path 

home = os.path.expanduser('~') 

Dies funktioniert sogar, wenn HOME nicht definiert ist, und verallgemeinert zu Nachschlagen Home-Verzeichnisse anderer Benutzer (os.path.expanduser('~someotheruser')).

In Python 3.5+ könnten Sie auch use pathlib.Path.home() to get a Path object representing the home directory.

Auch tangential, wenn Sie eine Zeichenfolge mit einem Bündel von Umgebungsvariablen Ersatz im Allgemeinen erweitern müssen, sollten Sie bei os.path.expandvars suchen, die das Umwelt-Lookup und String funktioniert die Formatierung in einem einzigen Vorgang.

Verwandte Themen