Генерировать произвольную строку UTF-8 в Python

19

Я хочу проверить обработку Юникодом моего кода. Есть ли что-нибудь, что я могу поставить в 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

Люди могут найти свой путь здесь, основываясь главным образом на заголовке вопроса, поэтому вот способ создания случайной строки, содержащей множество символов Юникода. Чтобы включить больше (или меньше) возможных символов, просто расширьте эту часть примера с помощью диапазонов кодовых точек, которые вы хотите.

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
2

Выполняет код, который печатает любой печатный символ 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