Python 3.x 在Python中写入派生进程的重定向输入

Python 3.x 在Python中写入派生进程的重定向输入,python-3.x,Python 3.x,对不起,我真的不是一个python人,但是这种情况打击了我,这对python人来说是非常明显的 我正在尝试与衍生的控制台进程进行交互通信(在我们的用例中,它是一个控制台程序,用于与旧的但仍然很好的HP仪器进行通信,以便在实验中测量一些物理变量)。 我在这里找到了一些有见地的例子: 但当我试图获得灵感时(我不想要那个计时器),我开始从头开始写这篇文章,用一个ftp.exe程序进行测试,该程序通常出现在windows设备上,具有以下特点: #!/usr/bin/python import subp

对不起,我真的不是一个python人,但是这种情况打击了我,这对python人来说是非常明显的

我正在尝试与衍生的控制台进程进行交互通信(在我们的用例中,它是一个控制台程序,用于与旧的但仍然很好的HP仪器进行通信,以便在实验中测量一些物理变量)。
我在这里找到了一些有见地的例子:

但当我试图获得灵感时(我不想要那个计时器),我开始从头开始写这篇文章,用一个ftp.exe程序进行测试,该程序通常出现在windows设备上,具有以下特点:

#!/usr/bin/python
import subprocess, sys
mystdout=sys.stdout
p = subprocess.Popen("ftp.exe", stdin=subprocess.PIPE, stdout=subprocess.PIPE) #, shell=True)
sys.stdout=p.stdin
print('bye\n'.encode())
sys.stdout=mystdout
print('done')
但是
打印('bye\n'.encode())
会导致:

print('bye\n'.encode())

TypeError:需要类似字节的对象,而不是'str'

我不能使用子流程的
communicate()
方法,因为它似乎不是非常交互式的(仅限一次性)


请你给我一个提示,我的哑巴在哪里?这台机器在Windows上运行Python 3.6.1,但是一台更友好的Linux机器在3.7.3上也会发出同样的问候。

有趣的是,我刚刚发现

universal\u newlines=True

因为
Popen()
的最后一个参数解决了我的问题。我猜流不喜欢
print()
,因为它是以二进制模式打开的。添加此标志将以文本模式打开流。我会发布一个完整的例子,包括互动交流,当我有它

编辑:

哦,现在我找到了更多与这个问题相关的资源

在Linux上似乎更容易,因为有fcntl包允许 使用非阻塞读取()设置管道。不幸的是,它似乎在Windows上不可用:( 我本来希望使用peek()调用,但是出乎意料,出乎意料,它也是 管道堵塞!:(

因此,我们要么使用线程,要么使用现代的难以理解的异步/等待样式

基于以上链接的灵感,我得到了以下简单的ftp工作示例:

#!/usr/bin/python

import time, sys, subprocess, threading, queue

def enqueue_output(out, queue):
    for line in iter(out.readline, b''):
        queue.put(line)
    out.close()    

def getOutput(outQueue):
    outStr = ''
    try:
        while True: 
            outStr+=outQueue.get_nowait()

    except queue.Empty:
        return outStr           

p = subprocess.Popen("ftp.exe", stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) 

outQueue = queue.Queue()
errQueue = queue.Queue()

outThread = threading.Thread(target=enqueue_output, args=(p.stdout, outQueue))
errThread = threading.Thread(target=enqueue_output, args=(p.stderr, errQueue))

outThread.daemon = True
errThread.daemon = True

outThread.start()
errThread.start()

p.stdin.write('status\n')
p.stdin.flush()
time.sleep(0.2)

errors = getOutput(errQueue)
output = getOutput(outQueue)

print("err:" + errors)
print("out:" + output)

time.sleep(2)

p.stdin.write('help\n')
p.stdin.flush()
time.sleep(0.2)

errors = getOutput(errQueue)
output = getOutput(outQueue)

print("err:" + errors)
print("out:" + output)

time.sleep(2)

p.stdin.write('bye\n')
p.stdin.flush()
time.sleep(0.2)

errors = getOutput(errQueue)
output = getOutput(outQueue)

print("err:" + errors)
print("out:" + output)

time.sleep(2)

print('done')
<>最后一个注释:当使用这个程序与我自己的C++程序通信时,我必须在每次输出之后发布<代码> FFLUHUT(STDUT)。甚至连换行也不会帮助这些东西在没有冲洗的情况下掉进管道。< /P>