How to fix an encoding migrating Python subprocess to unicode_literals?

自古美人都是妖i 提交于 2019-12-05 09:23:39

'%s\n' is a unicode string when you use unicode_literals:

>>> line = u'¡Basta Ya!'
>>> '%s\n' % line.encode(u'utf-8')
'\xc2\xa1Basta Ya!\n'
>>> u'%s\n' % line.encode(u'utf-8')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 0: ordinal not in range(128)

What happens is that your encoded line value is being decoded to interpolate into the unicode '%s\n' string.

You'll have to use a byte string instead; prefix the string with b:

>>> from __future__ import unicode_literals
>>> line = u'¡Basta Ya!'
>>> b'%s\n' % line.encode(u'utf-8')
'\xc2\xa1Basta Ya!\n'

or encode after interpolation:

>>> line = u'¡Basta Ya!'
>>> ('%s\n' % line).encode(u'utf-8')
'\xc2\xa1Basta Ya!\n'

In Python 3, you'll have to write bytestrings to pipes anyway.

If utf-8 stands for your locale encoding then to communicate using Unicode strings, you could use universal_newlines=True on Python 3:

#!/usr/bin/env python3
from subprocess import Popen, PIPE

p = Popen(['/path/to/binary/utility', '-l', 'nl'],
          stdin=PIPE, stdout=PIPE, stderr=PIPE,
          universal_newlines=True)
out, err = p.communicate('¡Basta Ya!')

The code works even if the locale's encoding is not utf-8. Input/output are Unicode strings here (str type).

If the subprocess requires utf-8 whatever the current locale is then communicate using bytestrings instead (pass/read bytes):

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import os
from subprocess import Popen, PIPE

p = Popen(['/path/to/binary/utility', '-l', 'nl'],
          stdin=PIPE, stdout=PIPE, stderr=PIPE)
out, err = map(lambda b: b.decode('utf-8').replace(os.linesep, '\n'),
               p.communicate((u'¡Basta Ya!' + os.linesep).encode('utf-8')))

The code works the same on both Python 2 and 3.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!