문제

다음을 수행하면 :

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

나는 얻다:

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'

분명히 cstringio.stringio 객체는 하위 프로세스에 적합한 파일 오리에 충분히 가깝지 않습니다. 이 문제를 어떻게 해결합니까?

도움이 되었습니까?

해결책

Popen.communicate() 선적 서류 비치:

프로세스의 stdin에 데이터를 보내려면 stdin = 파이프로 Popen 객체를 만들어야합니다. 마찬가지로, 결과 튜플에서 아무것도 얻지 못하는 것을 얻으려면 stdout = 파이프 및/또는 stderr = 파이프도 제공해야합니다.

OS.Popen 교체*

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

경고 다른 OS 파이프 버퍼가 채우고 차단하는 다른 OS 파이프 버퍼로 인해 교착 상태를 피하기 위해 stdin.write (), stdout.read () 또는 stderr.read () 대신 Communice ()를 사용하십시오.

따라서 예제는 다음과 같이 쓸 수 있습니다.

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
# ->

현재 Python 3 버전에서는 사용할 수 있습니다. subprocess.run, 입력을 외부 명령으로 문자열로 전달하고 출구 상태를 얻고 한 번의 호출에서 출력을 다시 문자열로 가져옵니다.

#!/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
# -> 

다른 팁

이 해결 방법을 알아 냈습니다.

>>> 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()

더 나은 것이 있습니까?

나는 아무도 파이프를 만드는 것을 제안하지 않았다는 사실에 약간 놀랐습니다. 제 생각에는 서브 프로세스의 stdin에게 문자열을 전달하는 가장 간단한 방법입니다.

read, write = os.pipe()
os.write(write, "stdin input here")
os.close(write)

subprocess.check_call(['your-command'], stdin=read)

Python 3.4 이상을 사용하는 경우 아름다운 솔루션이 있습니다. 사용 input 대신 인수 stdin 바이트 인수를 받아들이는 인수 :

output = subprocess.check_output(
    ["sed", "s/foo/bar/"],
    input=b"foo",
)

Python3을 사용하고 있으며 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)

"분명히 cstringio.stringio 객체는 하위 프로세스에 맞게 파일 오리에 충분히 가깝지 않습니다."

:-)

난 두려워하지. 파이프는 저수준 OS 개념이므로 OS 레벨 파일 디스크립터로 표시되는 파일 개체가 절대적으로 필요합니다. 귀하의 해결 방법은 올바른 일입니다.

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()
"""
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()

조심하십시오 Popen.communicate(input=s)만약 당신에게 문제를 줄 수 있습니다s학부모 프로세스가 버퍼링 될 것이기 때문에 너무 큽니다. ~ 전에 아동 하위 프로세스를 포킹하는데, 그 시점에서 "두 배나 많은"메모리가 필요하다는 것을 의미합니다 (적어도 "Hend the Hood"설명 및 연결된 문서에 따라 여기). 내 특별한 경우,s처음으로 완전히 확장 된 발전기였습니다.stdin 따라서 부모의 과정은 아이가 생성되기 직전에 엄청 났으며, 그것을 포크 할 기억이 남아 있지 않았습니다.

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

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)
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top