2013-09-25 3 views
5

Я уверен, выполнение подпроцесса с помощью Popen и подачи его ввода следующим образом (с помощью Python 2.7.4):Popen подпроцесс не выходит, когда STDIN включает юникода

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

+0

На самом деле лучше указать версию _exact_, потому что есть основной переписывающий 'message' в 3.2, а некоторые важные исправления ошибок в Версии 2.7.x и 3.1.x ... – abarnert

+0

Его программа имеет описанный симптом как в 2.7.4, так и в 3.3.1. Это происходит только тогда, когда вход содержит широкие символы UTF-8. Это имеет какое-то отношение к 'chasen', так как при замене этого' cat', он работает нормально. Но из командной строки 'chasen' также работает нормально. – nickie

ответ

2

Это ошибка в часене. При запуске через Python, вы можете увидеть следующие системные вызовы, она выдает:

write(1, "\n", 1)      = 1 
read(0, "", 4096)      = 0 
write(1, "\n", 1)      = 1 
read(0, "", 4096)      = 0 

т.е. не правильно обрабатывать EOF. Чтобы исправить это, просто наклеить на новую строку ('\n') в строку Python, например:

# 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) 
+0

Отлично, это действительно исправление. Благодаря! – nedned

Смежные вопросы