Popen子进程包含Unicode字符时,stdin无法退出

5

我正在使用 Popen 执行一个子进程,并按照以下方式提供输入(使用 Python 2.7.4):

env = dict(os.environ)
env['LC_ALL'] = 'en_US.UTF-8'
args = ['chasen', '-i u', '-F"%m "']
process = Popen(args, stdout=PIPE, stderr=PIPE, stdin=PIPE, env=env)
out, err = process.communicate(input=string)

将条目添加到执行环境中是必要的,因为输入字符串包含日语字符,当脚本不是从命令行执行时(在我的情况下由Apache调用),Python无法猜测编码。对于其他命令,此设置对我有效,但现在我正在使用日本分词器“chasen”,每当我发送Unicode字符时,子进程都不会返回,并且Python脚本一直占用内存。这似乎是一个编码问题,但我认为通过指定具有“LC_ALL”环境变量的编码方式来解决了这个问题。 编辑:以下是额外的怪异性......当从命令行执行Python脚本时,我不会遇到这个问题,特别是对于“。”这个字符。由于某种原因,这也引起了来自“chasen”的奇怪情况。

1
Python 2.x还是3.x?(当你处理Unicode问题时,两者的答案几乎总是非常不同。) - abarnert
“@nickie:你所说的“宽UTF-8”是指不是1个字节,不在BMP范围内,还是其他什么?” - abarnert
@nickie:这些字符在UTF-8中都是3字节,但都在BMP范围内,这至少很奇怪。如果你只是在shell上运行echo "悪妻は百年の不作。" | chasen -i u '-F"%m "',它能正常工作吗? - abarnert
@abarnert:我正在使用Python 2.7.4。 - nedned
是的,在命令行上运行它很好,但当我从Python脚本中调用它时,它会失败。在这种情况下,问题出在特定的“。”字符上(请参见帖子中添加的信息)。删除该字符可以解决问题。然而,当通过Apache调用Python脚本时,问题出现在任何日语字符上,删除该字符无法解决问题。 - nedned
显示剩余8条评论
1个回答

2
这是chasen中的一个bug。当通过Python运行时,您可以看到它发出以下系统调用:
write(1, "\n", 1)                       = 1
read(0, "", 4096)                       = 0
write(1, "\n", 1)                       = 1
read(0, "", 4096)                       = 0

即它不能正确处理EOF。要解决这个问题,只需在你的Python字符串后面加上一个换行符('\n'),像这样:
# coding: utf-8
import os
from subprocess import Popen, PIPE

string = u"悪妻は百年の不作。"

env = dict(os.environ)
env['LC_ALL'] = 'en_US.UTF-8'
args = ['chasen', '-i u', '-F"%m "']
process = Popen(args, stdout=PIPE, stderr=PIPE, stdin=PIPE, env=env)
out, err = process.communicate(input=(string + u'\n').encode('utf-8'))

print(out)

完美,确实解决了问题。谢谢! - nedned

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接