在Python中生成随机UTF-8字符串
我想测试一下我的代码对Unicode的处理能力。有没有什么方法可以在random.choice()里选择整个Unicode范围的字符,最好是不使用外部模块?在Google和StackOverflow上似乎都没有找到答案。
补充一下:看起来这个问题比我想的要复杂,所以我换个说法——下面的代码是否足够生成所有有效的非控制字符的Unicode?
unicode_glyphs = ''.join(
unichr(char)
for char in xrange(1114112) # 0x10ffff + 1
if unicodedata.category(unichr(char))[0] in ('LMNPSZ')
)
8 个回答
9
这里有一个示例函数,它可能会生成一个随机的、格式正确的UTF-8序列,这个序列的定义可以在Unicode 5.0.0的表3-7中找到:
#!/usr/bin/env python3.1
# From Table 3–7 of the Unicode Standard 5.0.0
import random
def byte_range(first, last):
return list(range(first, last+1))
first_values = byte_range(0x00, 0x7F) + byte_range(0xC2, 0xF4)
trailing_values = byte_range(0x80, 0xBF)
def random_utf8_seq():
first = random.choice(first_values)
if first <= 0x7F:
return bytes([first])
elif first <= 0xDF:
return bytes([first, random.choice(trailing_values)])
elif first == 0xE0:
return bytes([first, random.choice(byte_range(0xA0, 0xBF)), random.choice(trailing_values)])
elif first == 0xED:
return bytes([first, random.choice(byte_range(0x80, 0x9F)), random.choice(trailing_values)])
elif first <= 0xEF:
return bytes([first, random.choice(trailing_values), random.choice(trailing_values)])
elif first == 0xF0:
return bytes([first, random.choice(byte_range(0x90, 0xBF)), random.choice(trailing_values), random.choice(trailing_values)])
elif first <= 0xF3:
return bytes([first, random.choice(trailing_values), random.choice(trailing_values), random.choice(trailing_values)])
elif first == 0xF4:
return bytes([first, random.choice(byte_range(0x80, 0x8F)), random.choice(trailing_values), random.choice(trailing_values)])
print("".join(str(random_utf8_seq(), "utf8") for i in range(10)))
由于Unicode标准非常庞大,我无法对这个函数进行全面测试。另外,请注意,这些字符的分布并不是均匀的(但序列中的每个字节是均匀分布的)。
25
人们可能会根据问题的标题找到这里,所以这里有一种方法可以生成一个包含各种Unicode字符的随机字符串。如果你想要包含更多(或更少)的字符,只需在示例中扩展你想要的字符范围即可。
import random
def get_random_unicode(length):
try:
get_char = unichr
except NameError:
get_char = chr
# Update this to include code point ranges to be sampled
include_ranges = [
( 0x0021, 0x0021 ),
( 0x0023, 0x0026 ),
( 0x0028, 0x007E ),
( 0x00A1, 0x00AC ),
( 0x00AE, 0x00FF ),
( 0x0100, 0x017F ),
( 0x0180, 0x024F ),
( 0x2C60, 0x2C7F ),
( 0x16A0, 0x16F0 ),
( 0x0370, 0x0377 ),
( 0x037A, 0x037E ),
( 0x0384, 0x038A ),
( 0x038C, 0x038C ),
]
alphabet = [
get_char(code_point) for current_range in include_ranges
for code_point in range(current_range[0], current_range[1] + 1)
]
return ''.join(random.choice(alphabet) for i in range(length))
if __name__ == '__main__':
print('A random string: ' + get_random_unicode(10))
10
这里有一个来自Markus Kuhn的UTF-8压力测试,你可以用来测试。
另外,你也可以看看这个非常好的、糟糕的UTF-8示例测试数据。