这是我在python2中编写的一个例子
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import print_function
import sys, struct
def pack(*s_list):
return b"".join(struct.pack(">I", len(s)) + s for s in s_list)
if __name__ == "__main__":
print(sys.version)
a = pack("α", "привет мир", "±")
b = b"\x00\x00\x00\x02α\x00\x00\x00\x13привет мир\x00\x00\x00\x02±"
print(a == b)
转换后的python 3代码,
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys, struct
def pack(*s_list):
return b"".join(struct.pack(">I", len(b)) + b for b in (s.encode() for s in s_list))
if __name__ == "__main__":
print(sys.version)
a = pack("α", "привет мир", "±")
b = b"\x00\x00\x00\x02α" + "α".encode() + b"\x00\x00\x00\x13" + "привет мир".encode() + b"\x00\x00\x00\x02" + "±".encode()
print(a == b)
我注意到在python 3中使用b = b"\x00\x00\x00\x02α\x00\x00\x00\x13привет мир\x00\x00\x00\x02±"
将获得异常SyntaxError: bytes can only contain ASCII literal characters.
,
所以我不得不逃避它们或使用许多+像之前的代码一样。
有没有更好的方法来声明字节数组包含python3中的非ascii字符?
答案 0 :(得分:2)
另一种解决方案:
b = bytes("привет мир", 'utf-8')
似乎它是更好的解决方案,因为它具有较少的复制操作。
答案 1 :(得分:1)
如果您知道字符的编码字节表示,请直接使用它。字节和字节数组根本不包含字符 - 这是字符串/字节区别的全部要点。它们包含可能表示某些特定编码中的字符的字节。我认为该异常文本有点误导 - 字节对象的文字表示只能包含ASCII字符,但这并不意味着对象本身只包含ASCII字符,而不是通过解析表达式{{1包含ASCII字符。
[int("6")]
以UTF-8编码为'α'
,因此您可以将字节构建为b'\xce\xb1'
等。
如果您事先不知道相应的字节,使用b=b"\x00\x00\x00\x02\xce\xb1\x00\x00\x00\x13"
生成它们是最好的选择。
答案 2 :(得分:1)
这似乎在Python 3.3.2中正常工作:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
b = bytearray("\x00\x00\x00\x02α\x00\x00\x00\x13привет мир"
"\x00\x00\x00\x02±".encode())
答案 3 :(得分:0)
最后我找到了一个解决方案,这是一个例子:
def to_bytes(string):
result = b""
need_eval = ""
need_encode = ""
for char in string:
if char <= "\x7f":
# if char is ascii, eval it with in b'...'
if need_encode:
result += need_encode.encode()
need_encode = ""
if char == "'":
n = 0
# get how many \ in the end of need_eval
for v in reversed(need_eval):
if v != "\\":
break
n += 1
# if ' is not escaping
if n % 2 == 0:
char = "\\'"
need_eval += char
else:
# if char is non-ascii, encode it to utf-8
if need_eval:
result += ast.literal_eval("b'" + need_eval + "'")
need_eval = ""
need_encode += char
result += need_encode.encode()
result += ast.literal_eval("b'" + need_eval + "'")
return result
b = to_bytes(r"\x00\x00\x00\x02α\x00\x00\x00\x13привет мир\x00\x00\x00\x02±")
print(repr(b))
print(to_bytes(r"±\xb1"))
print(to_bytes(r"\x90asdfg\\'\''\r\n\xff\u0001"))
指向非ascii部分进行编码并将其他部分转换为eval(因为在python 3上没有string_escape编码,我必须使用ast.literal_eval)。
痛苦是没有效率。
答案 4 :(得分:0)
Python 2函数的工作翻译是:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys, struct
def pack(*s_list):
# The original passed byte strings encoded in utf-8.
# I convert the Python 3 Unicode strings to UTF-8 explicitly here.
s_list = [s.encode('utf8') for s in s_list]
return b"".join(struct.pack(">I", len(s)) + s for s in s_list)
if __name__ == "__main__":
print(sys.version)
a = pack("α", "привет мир", "±")
# In Python 2 Unicode characters in byte strings were implicitly in the encoding
# of the file (utf8 above). Python 3 must be explicit.
b = "\x00\x00\x00\x02α\x00\x00\x00\x13привет мир\x00\x00\x00\x02±".encode('utf8')
print(a == b)