只打印字符串的内容
Print only the contents of a string
这是我的代码:
#! /usr/bin/env python3
import subprocess
a = subprocess.check_output('echo -n "hello world!"',shell=True)
print("a="+str(a))
输出:
a=b'hello world!'
如果我在对 check_output
的调用中包含参数 universal_newlines=True
,那么我会得到所需的输出:
a=hello world!
为了更好地理解现代(Unicode)时代文本编程的神秘世界,我想知道如何在不指定universal_newlines=True
的情况下生成第二个输出。换句话说,我调用什么函数来转换 a
以便它产生所需的输出。
一个工作示例会大有帮助。详细的解释很好,但对于外行来说它们往往有点令人困惑——可能是由于使用了过多的术语,可能是因为 Python2 和 Python3 之间的差异,或者只是因为我非常在我的工作中很少需要考虑文本编码——我使用的大多数工具不需要像这样的特殊处理。
另外:我相信第一个输出的类型是 bytes
,但是第二个输出的类型是什么?我的猜测是 str
使用 UTF-8 编码。
正如 Ignacio 的评论最初暗示的那样,您可以使用 decode
:
>>> a = b"hello world!"
>>> print("a="+str(a))
a=b'hello world!'
>>> print("a="+a.decode())
a=hello world!
Also: I believe the first output is of type
bytes
, but
what is the type of the second output? My guess is
str
with UTF-8
encoding.
接近,但不太正确。在 Python3 和 str
type is indexed by Unicode code points (note that code points usually, but not always, have a 1:1 correspondence with user perceived characters). Therefore, the underlying encoding is abstracted away when using the str
type -- consider it unencoded, even though that is fundamentally not the case. It is the bytes
type which is indexed as a simple array of bytes and therefore must use a particular encoding 中,在这种情况下(在大多数类似的用法中),ASCII
足以解码子进程脚本生成的内容。
Python2 对 str
类型 (see here) 的解释有不同的默认值,因此字符串文字在该语言版本中将以不同的方式表示(这种差异可能是研究文本处理时的一大绊脚石。
作为一个主要使用 C++ 的人,我发现以下内容对于 Unicode 文本的实际存储、编码和索引非常有启发性:How do I use 3 and 4-byte Unicode characters with standard C++ strings?
所以问题第一部分的答案是bytes.decode()
:
a = a.decode('ascii') ## convert from `bytes` to 'str' type
虽然只是简单地使用
a = a.decode() ## assumes UTF-8 encoding
通常会产生相同的结果,因为 ASCII 是 UTF-8 的子集。
或者,您可以像这样使用 str()
:
a = str(a,encoding='ascii')
但请注意,如果您想要 "contents only" 表示,则必须在此处指定编码 - 否则它实际上会构建一个 str
类型,该类型内部包含引号字符(包括 'b' 前缀),这正是问题中显示的第一个输出中发生的情况。
subprocess.check_output
默认以 binary 模式(returning 原始字节序列)处理数据,但神秘的参数 universal_newlines=True
基本上告诉它 解码 字符串并将其表示为 text (使用 str
类型)。如果您想使用 Python 的 print
函数显示输出(和 "only the contents"),则必须转换为 str
类型(在 Python3 中)。
这种转换的有趣之处在于,出于这些目的,它实际上对数据没有任何影响。引擎盖下发生的是一个实现细节,但如果数据是 ASCII(对于此类程序非常典型),它基本上只是从一个地方复制到另一个地方而没有任何有意义的翻译。 decode 操作只是 hoop jumping to change the data type -- and the seemingly pointless nature of the operation further obfuscates the larger vision behind Python's text handling (for the uninitiated). Further, since the docs 不要使 return 类型显式(按名称),甚至很难知道从哪里开始寻找适当的转换函数。
来自 subprocess.check_output()
docs:
By default, this function will return the data as encoded bytes. The
actual encoding of the output data may depend on the command being
invoked, so the decoding to text will often need to be handled at the
application level.
This behaviour may be overridden by setting universal_newlines
to True
as described below in Frequently Used Arguments.
如果按照link到Frequently Used Arguments;它描述了 universal_newlines=True
的作用:
If universal_newlines
is False
the file objects stdin, stdout and
stderr will be opened as binary streams, and no line ending conversion
is done.
If universal_newlines
is True
, these file objects will be opened as
text streams in universal newlines mode using the encoding returned by
locale.getpreferredencoding(False)
. For stdin, line ending characters
'\n'
in the input will be converted to the default line separator
os.linesep
. For stdout and stderr, all line endings in the output will
be converted to '\n'
. For more information see the documentation of
the io.TextIOWrapper
class when the newline argument to its
constructor is None
.
有关详细信息,您可以查看 io.TextIOWrapper()
documentation。
到 运行 你的 echo -n "hello world!"
shell 命令和到 return 没有 check_output()
且没有使用 universal_newlines=True
的文本:
#!/usr/bin/env python
import locale
from subprocess import Popen, PIPE
charset = locale.getpreferredencoding(False)
with Popen(['echo', 'Hello world!'], stdout=PIPE) as process:
output = process.communicate()[0].decode(charset).strip()
这是 that show how subprocess
pipes and TextIOWrapper
class could be used together.
要了解 Python 中的文本和二进制数据,请阅读 Unicode HOWTO。这是最重要的部分:Python 中有两种主要的字符串类型:表示二进制数据的字节串(字节序列)和表示人类可读文本的 Unicode 字符串(Unicode 代码点序列)。一个转换成另一个很简单(☯):
unicode_text = bytestring.decode(character_encoding)
bytestring = unicode_text.encode(character_encoding)
这是我的代码:
#! /usr/bin/env python3
import subprocess
a = subprocess.check_output('echo -n "hello world!"',shell=True)
print("a="+str(a))
输出:
a=b'hello world!'
如果我在对 check_output
的调用中包含参数 universal_newlines=True
,那么我会得到所需的输出:
a=hello world!
为了更好地理解现代(Unicode)时代文本编程的神秘世界,我想知道如何在不指定universal_newlines=True
的情况下生成第二个输出。换句话说,我调用什么函数来转换 a
以便它产生所需的输出。
一个工作示例会大有帮助。详细的解释很好,但对于外行来说它们往往有点令人困惑——可能是由于使用了过多的术语,可能是因为 Python2 和 Python3 之间的差异,或者只是因为我非常在我的工作中很少需要考虑文本编码——我使用的大多数工具不需要像这样的特殊处理。
另外:我相信第一个输出的类型是 bytes
,但是第二个输出的类型是什么?我的猜测是 str
使用 UTF-8 编码。
正如 Ignacio 的评论最初暗示的那样,您可以使用 decode
:
>>> a = b"hello world!"
>>> print("a="+str(a))
a=b'hello world!'
>>> print("a="+a.decode())
a=hello world!
Also: I believe the first output is of type
bytes
, but what is the type of the second output? My guess isstr
with UTF-8 encoding.
接近,但不太正确。在 Python3 和 str
type is indexed by Unicode code points (note that code points usually, but not always, have a 1:1 correspondence with user perceived characters). Therefore, the underlying encoding is abstracted away when using the str
type -- consider it unencoded, even though that is fundamentally not the case. It is the bytes
type which is indexed as a simple array of bytes and therefore must use a particular encoding 中,在这种情况下(在大多数类似的用法中),ASCII
足以解码子进程脚本生成的内容。
Python2 对 str
类型 (see here) 的解释有不同的默认值,因此字符串文字在该语言版本中将以不同的方式表示(这种差异可能是研究文本处理时的一大绊脚石。
作为一个主要使用 C++ 的人,我发现以下内容对于 Unicode 文本的实际存储、编码和索引非常有启发性:How do I use 3 and 4-byte Unicode characters with standard C++ strings?
所以问题第一部分的答案是bytes.decode()
:
a = a.decode('ascii') ## convert from `bytes` to 'str' type
虽然只是简单地使用
a = a.decode() ## assumes UTF-8 encoding
通常会产生相同的结果,因为 ASCII 是 UTF-8 的子集。
或者,您可以像这样使用 str()
:
a = str(a,encoding='ascii')
但请注意,如果您想要 "contents only" 表示,则必须在此处指定编码 - 否则它实际上会构建一个 str
类型,该类型内部包含引号字符(包括 'b' 前缀),这正是问题中显示的第一个输出中发生的情况。
subprocess.check_output
默认以 binary 模式(returning 原始字节序列)处理数据,但神秘的参数 universal_newlines=True
基本上告诉它 解码 字符串并将其表示为 text (使用 str
类型)。如果您想使用 Python 的 print
函数显示输出(和 "only the contents"),则必须转换为 str
类型(在 Python3 中)。
这种转换的有趣之处在于,出于这些目的,它实际上对数据没有任何影响。引擎盖下发生的是一个实现细节,但如果数据是 ASCII(对于此类程序非常典型),它基本上只是从一个地方复制到另一个地方而没有任何有意义的翻译。 decode 操作只是 hoop jumping to change the data type -- and the seemingly pointless nature of the operation further obfuscates the larger vision behind Python's text handling (for the uninitiated). Further, since the docs 不要使 return 类型显式(按名称),甚至很难知道从哪里开始寻找适当的转换函数。
来自 subprocess.check_output()
docs:
By default, this function will return the data as encoded bytes. The actual encoding of the output data may depend on the command being invoked, so the decoding to text will often need to be handled at the application level.
This behaviour may be overridden by setting
universal_newlines
toTrue
as described below in Frequently Used Arguments.
如果按照link到Frequently Used Arguments;它描述了 universal_newlines=True
的作用:
If
universal_newlines
isFalse
the file objects stdin, stdout and stderr will be opened as binary streams, and no line ending conversion is done.If
universal_newlines
isTrue
, these file objects will be opened as text streams in universal newlines mode using the encoding returned bylocale.getpreferredencoding(False)
. For stdin, line ending characters'\n'
in the input will be converted to the default line separatoros.linesep
. For stdout and stderr, all line endings in the output will be converted to'\n'
. For more information see the documentation of theio.TextIOWrapper
class when the newline argument to its constructor isNone
.
有关详细信息,您可以查看 io.TextIOWrapper()
documentation。
到 运行 你的 echo -n "hello world!"
shell 命令和到 return 没有 check_output()
且没有使用 universal_newlines=True
的文本:
#!/usr/bin/env python
import locale
from subprocess import Popen, PIPE
charset = locale.getpreferredencoding(False)
with Popen(['echo', 'Hello world!'], stdout=PIPE) as process:
output = process.communicate()[0].decode(charset).strip()
这是 subprocess
pipes and TextIOWrapper
class could be used together.
要了解 Python 中的文本和二进制数据,请阅读 Unicode HOWTO。这是最重要的部分:Python 中有两种主要的字符串类型:表示二进制数据的字节串(字节序列)和表示人类可读文本的 Unicode 字符串(Unicode 代码点序列)。一个转换成另一个很简单(☯):
unicode_text = bytestring.decode(character_encoding)
bytestring = unicode_text.encode(character_encoding)