Генерация случайной строки UTF-8 в Python

21

Я бы хотел проверить обработку Unicode моего кода. Что-нибудь, что я могу поместить в random.choice (), чтобы выбрать из всего диапазона Unicode, предпочтительно не внешний модуль? Кажется, что ни у Google, ни у StackOverflow нет ответа.

Редактировать. Похоже, что это сложнее, чем ожидалось, поэтому я перефразирую вопрос: достаточно ли следующего кода для генерации всех действительных неконтролируемые символы в Юникоде ?

unicode_glyphs = ''.join(
    unichr(char)
    for char in xrange(1114112) # 0x10ffff + 1
    if unicodedata.category(unichr(char))[0] in ('LMNPSZ')
    )
    
задан l0b0 25.09.2009 в 15:29
источник
  • Это может помочь, если вы хотите дать более подробную информацию о «проверке обработки Юникодом моего кода» и объясните, что является частью, которая генерирует случайные строки UTF-8, чтобы играть в этом тестировании, и то, что вы считаете " весь диапазон Unicode "(16 бит? 21 бит? не суррогатные коды-коды? допустимые символы (например, не U + FFFF)?). Вы доверяете кодеку Python UTF-8, или вам нужно также проверить это? Python 2.X или 3.X или оба? –  John Machin 26.09.2009 в 01:10
  • Цель состоит в том, чтобы принять любые допустимые коды кода (символы) кода Unicode для печати в качестве входных данных для веб-интерфейса в Python 2.6. –  l0b0 28.09.2009 в 18:05

8 ответов

9
ответ дан Gumbo 25.09.2009 в 15:47
  • Было бы полезно убедиться, что программа не сломается при получении неверного текста, но это не помогло бы в качестве теста на соответствие. –  Esteban Küber 25.09.2009 в 15:49
  • +1. l0b0: не беспокойтесь о генерации случайного юникода. Заимствование чужого колеса> изобретает его. –  Matt Ball 25.09.2009 в 15:53
  • Хороший ответ, но на самом деле не отвечает на заданный вопрос. –  Kylotan 24.11.2012 в 22:08
  • Загрузка файла заблокирована на Mac Chrome 54.0.2840.59, но вы можете просмотреть его, нажав на него. –  Cat Zimmermann 15.10.2016 в 22:35
12

Люди могут найти свой путь здесь, основываясь главным образом на заголовке вопроса, так что вот способ генерировать случайную строку, содержащую множество символов 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))
    
ответ дан Jacob Wan 10.02.2014 в 00:34
  • Спасибо, Джейкоб. Были ли проблемы при запуске этого кода в Python 2.7? –  morfys 22.07.2015 в 23:49
  • @morfys Это не так, но я только что отредактировал его, так оно и есть. Спасибо за вопрос. –  Jacob Wan 23.07.2015 в 23:32
  • Большое спасибо, Джейкоб! –  morfys 23.07.2015 в 23:35
7

Вот пример функции, которая, вероятно, создает случайную правильно сформированную последовательность UTF-8, как определено в Таблице 3-7 Unicode 5.0.0:

#!/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 я не могу это тщательно проверить. Также обратите внимание, что символы распределены неравномерно (но каждый байт в последовательности).

    
ответ дан Philipp 25.09.2009 в 16:20
3

Это зависит от того, насколько тщательно вы хотите провести тестирование и насколько точно вы хотите выполнить генерацию. В целом, Unicode - это 21-битный кодовый набор (U + 0000 .. U + 10FFFF). Тем не менее, некоторые довольно большие куски этого диапазона отводятся для пользовательских символов. Хотите ли вы беспокоиться о создании комбинированных символов в начале строки (потому что они должны появляться только после другого символа)?

Базовый подход, который я бы выбрал, заключается в том, чтобы случайным образом генерировать кодовую точку Unicode (скажем, U + 2397 или U + 31232), проверять ее в контексте (является ли она допустимым символом; может ли она отображаться здесь в строке) и кодировать действительным кодовые точки в UTF-8.

Если вы просто хотите проверить, правильно ли ваш код обрабатывает искаженный UTF-8, вы можете использовать гораздо более простые схемы генерации.

Обратите внимание, что вам нужно знать, чего ожидать при вводе данных - в противном случае вы не тестируете; вы экспериментируете.

    
ответ дан Jonathan Leffler 25.09.2009 в 15:53
3

Следует код, который печатает любой печатный символ UTF-8:

print(''.join(tuple(chr(l) for l in range(1, 0x10ffff)
                    if chr(l).isprintable())))

Присутствуют все символы, даже те, которые не обрабатываются используемым шрифтом. Можно добавить and not chr(l).isspace() , чтобы отфильтровать все пробелы. (включая вкладку)

    
ответ дан aluriak 25.09.2016 в 02:57
  • Это на самом деле не даст вам случайную строку, хотя, конечно, вы можете просто использовать random.sample вместо печати. –  l0b0 25.09.2016 в 10:32
  • random.sample не заменяет элементы, которые он уже нарисовал. –  Gregory Nisbet 07.10.2016 в 04:18
  • Вместо этого используйте random.choices. –  gimboland 30.01.2018 в 14:20
0

Так как Unicode - это просто набор хорошо кодов, как насчет использования unichr () для получения строки unicode, соответствующей случайному числу от 0 до 0xFFFF?
(Конечно, это дало бы только одну кодовую точку, поэтому выполняйте итерацию по мере необходимости)

    
ответ дан Joril 25.09.2009 в 15:44
  • К сожалению, это не так просто. Unicode содержит намного больше, чем 0x100000 символов, и диапазон не подключен. Например, суррогатные значения никогда не должны отображаться как единые кодовые точки. Таким образом, вопрос о том, что представляет собой действительную строку UTF-8, является весьма нетривиальным. Подробности описаны в определении D92 главы 3 стандарта Unicode. Существует также таблица (3-7)), в которой перечислены все допустимые возможности для последовательностей байтов UTF-8. –  Philipp 25.09.2009 в 15:54
  • Я вижу, спасибо :) –  Joril 25.09.2009 в 15:56
  • Юникод работает от U + 0000 до U + 10FFFF; есть также многочисленные недопустимые коды, включая (как это бывает) U + FFFF. В стандарте Unicode сказано «<не символ» - значение FFFF гарантировано не является символом Unicode вообще ». –  Jonathan Leffler 25.09.2009 в 15:58
  • UTF-8 является кодировкой Unicode. –  ThomasH 01.10.2009 в 22:09
0

Вы можете загрузить веб-сайт, написанный на греческом или немецком языке, который использует Unicode, и передать его в свой код.

    
ответ дан Esteban Küber 25.09.2009 в 15:45
0

Отвечая на пересмотренный вопрос:

Да, по строгому определению «управляющих символов» - обратите внимание, что вы не будете включать CR, LF и TAB; это то, что вы хотите?

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

    
ответ дан John Machin 28.09.2009 в 16:47