- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我想从 python 调用外部进程。我正在调用的进程读取输入字符串并给出标记化结果,然后等待另一个输入(如果有帮助,二进制是 MeCab 标记器)。
我需要通过调用此过程来标记数千行字符串。
问题是 Popen.communicate()工作但在给出 STDOUT 结果之前等待进程结束。我不想继续关闭和打开新的子流程数千次。 (而且我不想发送整个文本,将来很容易超过数万行。)
from subprocess import PIPE, Popen
with Popen("mecab -O wakati".split(), stdin=PIPE,
stdout=PIPE, stderr=PIPE, close_fds=False,
universal_newlines=True, bufsize=1) as proc:
output, errors = proc.communicate("foobarbaz")
print(output)
我试过阅读 proc.stdout.read()
而不是使用 communicate 但它被 stdin
阻止并且在 proc.stdin.close()
之前不返回任何结果叫做。这又意味着我每次都需要创建一个新流程。
我已经尝试通过类似的问题实现队列和线程,如下所示,但它要么不返回任何东西,因此它停留在 While True
上,或者当我强制 stdin 缓冲区填充时重复发送字符串,一次输出所有结果。
from subprocess import PIPE, Popen
from threading import Thread
from queue import Queue, Empty
def enqueue_output(out, queue):
for line in iter(out.readline, b''):
queue.put(line)
out.close()
p = Popen('mecab -O wakati'.split(), stdout=PIPE, stdin=PIPE,
universal_newlines=True, bufsize=1, close_fds=False)
q = Queue()
t = Thread(target=enqueue_output, args=(p.stdout, q))
t.daemon = True
t.start()
p.stdin.write("foobarbaz")
while True:
try:
line = q.get_nowait()
except Empty:
pass
else:
print(line)
break
也查看了 Pexpect 路由,但它的 windows 端口不支持一些重要的模块(基于 pty 的模块),所以我也无法应用它。
我知道有很多类似的答案,而且我已经尝试了其中的大部分。但我尝试过的任何东西似乎都无法在 Windows 上运行。
编辑:关于我正在使用的二进制文件的一些信息,当我通过命令行使用它时。它运行并标记我给出的句子,直到我完成并强行关闭程序。
(...waits_for_input -> input_recieved -> output -> waits_for_input...)
谢谢。
最佳答案
如果 mecab 使用带有默认缓冲的 C FILE
流,则管道标准输出有一个 4 KiB 缓冲区。这里的想法是,程序可以有效地使用小的、任意大小的读取和写入缓冲区,并且底层标准 I/O 实现处理自动填充和刷新更大的缓冲区。这最大限度地减少了所需的系统调用次数并最大限度地提高了吞吐量。显然,您不希望交互式控制台或终端 I/O 或写入 stderr
时出现这种行为。在这些情况下,C 运行时使用行缓冲或不使用缓冲。
程序可以覆盖此行为,并且某些程序确实具有设置缓冲区大小的命令行选项。例如,Python 具有“-u”(无缓冲)选项和 PYTHONUNBUFFERED
环境变量。如果 mecab 没有类似的选项,则 Windows 上没有通用的解决方法。 C运行时的情况太复杂了。 Windows 进程可以静态或动态链接到一个或多个 CRT。 Linux 上的情况不同,因为 Linux 进程通常将单个系统 CRT(例如 GNU libc.so.6)加载到全局符号表中,这允许 LD_PRELOAD
库配置 C FILE
流。 Linux stdbuf
使用这个技巧,例如stdbuf -o0 mecab -O wakati
。
一个试验选项是调用 CreateConsoleScreenBuffer
并从 msvcrt.open_osfhandle
获取句柄的文件描述符。然后将其作为 stdout
传递,而不是使用管道。子进程会将其视为 TTY 并使用行缓冲而不是全缓冲。然而,管理这一点并非易事。这将涉及读取(即 ReadConsoleOutputCharacter
)由另一个进程主动写入的滑动缓冲区(调用 GetConsoleScreenBufferInfo
以跟踪光标位置)。这种互动不是我曾经需要甚至尝试过的。但是我非交互地使用了控制台屏幕缓冲区,即在 child 退出后读取缓冲区。这允许从直接写入控制台而不是 stdout
的程序读取多达 9,999 行输出,例如调用 WriteConsole
或打开“CON”或“CONOUT$”的程序。
关于python - 子进程,从 STDOUT 读取时重复写入 STDIN (Windows),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42991214/
需要帮助将这些给定的数字打印成星号,但我是编程新手;我该怎么做? #include int main(void) { int a[5]={20,1,5,15,12}; int i=0
使用 Delphi XE 2 我试图确定缩放方向以将缩放效果应用于图像(TImage),但没有找到执行此操作的函数,并且图像的 OnGesture 事件中的 EventInfo 属性没有此信息. 我见
我不知道制服在内存中是如何表示的。 制服似乎会占用宝贵的寄存器空间,但它们最终会传入/通过/传出到全局内存中,对吗? 制服不用时情况会发生变化吗?编译器可以将它们优化掉吗?--在这种情况下,我已经将无
我正在尝试在名为“timeclock”的模型上记录“time_in”和“time_out”记录。这是我想做但无法开始工作的事情! 检查最后一个时钟条目,看看它是否同时填充了“time_in”和“tim
我想听听您如何解决这种编程任务!?每种类型(OPER = 1 类型)对应一种特定的信息。 这只是大约 10 个具有相同结构的规范之一。首选创建这些“转换器”(协议(protocol))的通用方法。 最
我正在使用 Rest API(NodeJS、Express)和 PostgreSQL 制作 React-Native 应用。 在我的本地机器上托管时一切正常。当 API 托管在我的机器上并且 Post
我是一名优秀的程序员,十分优秀!