Python - Kaip perduoti eilutę į subprocess.Popen (naudojant Stdin argumentą)?

Jei darau šiuos veiksmus:

 import subprocess from cStringIO import StringIO subprocess.Popen(['grep','f'],stdout=subprocess.PIPE,stdin=StringIO('one\ntwo\nthree\nfour\nfive\nsix\n')).communicate()[0] 

Gaunu:

 Traceback (most recent call last): File "<stdin>", line 1, in ? File "/build/toolchain/mac32/python-2.4.3/lib/python2.4/subprocess.py", line 533, in __init__ (p2cread, p2cwrite, File "/build/toolchain/mac32/python-2.4.3/lib/python2.4/subprocess.py", line 830, in _get_handles p2cread = stdin.fileno() AttributeError: 'cStringIO.StringI' object has no attribute 'fileno' 

Matyt, objektas cStringIO.StringIO neperkelia tiek arti failo anties, kad atitiktų subprocesą. Kaip tai padaryti?

218
02 окт. nustatė Daryl Spitzer 02 okt. 2008-10-02 20:25 '08 at 8:25 pm 2008-10-02 20:25
@ 10 atsakymų

Popen.communicate() dokumentacija:

Atkreipkite dėmesį, kad jei norite siųsti duomenis į stdin procesą, turite sukurti „Popen“ objektą naudodami STDIN = PIPE. Panašiai, norint gauti bet kurią kitą nei „Nieko“ rezultatas, reikia nurodyti stdout = PIPE ir / arba stderr = PIPE.

Os.popen * pakeitimas

  pipe = os.popen(cmd, 'w', bufsize) # ==> pipe = Popen(cmd, shell=True, bufsize=bufsize, stdin=PIPE).stdin 

Įspėjimas Naudokite jungties () funkciją, o ne stdin.write (), stdout.read () arba stderr.read (), kad išvengtumėte bet kokių kitų OS buferių užsikimšimo, užpildant ir užrakindami vaiko procesą.

Taigi, jūsų pavyzdys gali būti parašytas taip:

 from subprocess import Popen, PIPE, STDOUT p = Popen(['grep', 'f'], stdout=PIPE, stdin=PIPE, stderr=STDOUT) grep_stdout = p.communicate(input=b'one\ntwo\nthree\nfour\nfive\nsix\n')[0] print(grep_stdout.decode()) # -> four # -> five # -> 

Dabartinėje „Python 3“ versijoje galite naudoti subprocess.run perduoti įvestį kaip eilutę į išorinę komandą ir gauti išvesties būseną ir jos išvestį kaip eilutę vienu skambučiu:

 #!/usr/bin/env python3 from subprocess import run, PIPE p = run(['grep', 'f'], stdout=PIPE, input='one\ntwo\nthree\nfour\nfive\nsix\n', encoding='ascii') print(p.returncode) # -> 0 print(p.stdout) # -> four # -> five # -> 
244
03 окт. atsakymas pateikiamas jfs 03 okt. 2008-10-03 07:11 '08 at 7:11 AM 2008-10-03 07:11

Supratau šį problemą:

 >>> p = subprocess.Popen(['grep','f'],stdout=subprocess.PIPE,stdin=subprocess.PIPE) >>> p.stdin.write(b'one\ntwo\nthree\nfour\nfive\nsix\n') #expects a bytes type object >>> p.communicate()[0] 'four\nfive\n' >>> p.stdin.close() 

Ar yra geresnis?

33
02 окт. atsakymas, kurį pateikė Daryl Spitzer 02 okt. 2008-10-02 20:27 '08 at 8:27 pm 2008-10-02 20:27

Aš šiek tiek nustebęs, kad niekas nesiūlė sukurti kanalo, kuris, mano nuomone, yra paprasčiausias būdas perduoti eilutę į stdin subprocesą:

 read, write = os.pipe() os.write(write, "stdin input here") os.close(write) subprocess.check_call(['your-command'], stdin=read) 
16
02 нояб. Atsakymą pateikė Graham Christensen 02 lapkričio. 2015-11-02 19:34 '15 ne 19:34 2015-11-02 19:34

Aš naudoju python3 ir sužinojau, kad jums reikia koduoti eilutę, kol galėsite ją perduoti stdin:

 p = Popen(['grep', 'f'], stdout=PIPE, stdin=PIPE, stderr=PIPE) out, err = p.communicate(input='one\ntwo\nthree\nfour\nfive\nsix\n'.encode()) print(out) 
14
27 июля '14 в 18:29 2014-07-27 18:29 atsakymas pateikiamas liepos 27 d. 14 d., 18:29 2014-07-27 18:29

„Matyt, objektas cStringIO.StringIO neperkelia tiek arti failo anties, kad eitų į subprocesą.

: -)

Bijau ne. Vamzdis yra žemo lygio OS koncepcija, todėl jam būtinas objekto failas, kurį vaizduoja OS lygio failų deskriptorius. Jūsų sprendimas yra teisingas.

12
02 окт. atsakymas, kurį pateikė Dan Lenski 2008-10-02 21:33 '08, 21:33 2008-10-02 21:33
 from subprocess import Popen, PIPE from tempfile import SpooledTemporaryFile as tempfile f = tempfile() f.write('one\ntwo\nthree\nfour\nfive\nsix\n') f.seek(0) print Popen(['/bin/grep','f'],stdout=PIPE,stdin=f).stdout.read() f.close() 
9
13 апр. Atsakymą pateikė Michael Waddell , balandžio 13 d 2012-04-13 06:36 '12 6:36 2012-04-13 06:36

Yra gražus sprendimas, jei naudojate „Python 3.4“ ar naujesnę versiją. Vietoj stdin argumento naudokite input argumentą, kuris yra baito argumentas:

 output = subprocess.check_output( ["sed", "s/foo/bar/"], input=b"foo", ) 
8
08 дек. atsakymą pateikė Flimm 08 dec. 2016-12-08 13:04 '16 at 1:04 pm 2016-12-08 13:04
 """ Ex: Dialog (2-way) with a Popen() """ p = subprocess.Popen('Your Command Here', stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=PIPE, shell=True, bufsize=0) p.stdin.write('START\n') out = p.stdout.readline() while out: line = out line = line.rstrip("\n") if "WHATEVER1" in line: pr = 1 p.stdin.write('DO 1\n') out = p.stdout.readline() continue if "WHATEVER2" in line: pr = 2 p.stdin.write('DO 2\n') out = p.stdout.readline() continue """ .......... """ out = p.stdout.readline() p.wait() 
6
14 июня '13 в 16:20 2013-06-14 16:20 atsakymą pateikė Lucien Hercaud , birželio 14 d. 13 val. 16:20 2013-06-14 16:20

Būkite Popen.communicate(input=s) kad „ Popen.communicate(input=s) gali sukelti problemų, jei s per didelis, nes tėvų procesas gali jį buferis prieš pradedant naudoti vaiko subprocesą, t. „šiuo metu naudojama atmintis (bent jau pagal paaiškinimą„ po gaubtu “ir susijusi dokumentacija). Mano konkrečiu atveju, s buvo generatorius, kuris pirmą kartą buvo pilnai išplėstas ir tik tada parašytas stdin , taigi tėvų procesas buvo didžiulis prieš pat gimdymą ir nebuvo atminties, kad ją padalintų:

File "/opt/local/stow/python-2.7.2/lib/python2.7/subprocess.py", line 1130, in _execute_child self.pid = os.fork() OSError: [Errno 12] Cannot allocate memory

5
19 мая '14 в 17:56 2014-05-19 17:56 atsakymą pateikė Viešpats Henry Wotton gegužės 19 d. 14 d. 17:56 2014-05-19 17:56
 p = Popen(['grep', 'f'], stdout=PIPE, stdin=PIPE, stderr=STDOUT) p.stdin.write('one\n') time.sleep(0.5) p.stdin.write('two\n') time.sleep(0.5) p.stdin.write('three\n') time.sleep(0.5) testresult = p.communicate()[0] time.sleep(0.5) print(testresult) 
2
09 апр. atsakymą pateikė gedwarp 09 balandžio. 2009-04-09 07:39 '09, 7:39 2009-04-09 07:39

Kiti klausimai apie žymes arba Užduoti klausimą