with Genera una stringa UTF-8 casuale in Python




using popen python (7)

Mi piacerebbe testare la gestione Unicode del mio codice. C'è qualcosa che posso inserire in casual.choice () per selezionare dall'intero range Unicode, preferibilmente non un modulo esterno? Né Google né StackOverflow sembrano avere una risposta.

Modifica: Sembra che questo sia più complesso del previsto, quindi riformulerò la domanda: il seguente codice è sufficiente per generare tutti i caratteri validi non controllati in Unicode ?

unicode_glyphs = ''.join(
    unichr(char)
    for char in xrange(1114112) # 0x10ffff + 1
    if unicodedata.category(unichr(char))[0] in ('LMNPSZ')
    )


Dal momento che Unicode è solo un intervallo di - well - codes, per quanto riguarda l'utilizzo di unichr () per ottenere la stringa unicode corrispondente a un numero casuale compreso tra 0 e 0xFFFF?
(Ovviamente questo darebbe solo un punto di codice, quindi iterare come richiesto)


Rispondere alla domanda riveduta:

Sì, su una definizione rigorosa di "caratteri di controllo": nota che non includerai CR, LF e TAB; È questo che vuoi?

Per favore, considera la possibilità di rispondere al mio precedente invito a dirci cosa stai realmente cercando di fare.


Le persone possono trovare la loro strada qui basandosi principalmente sul titolo della domanda, quindi ecco un modo per generare una stringa casuale contenente una varietà di caratteri Unicode. Per includere più (o meno) caratteri possibili, estendi semplicemente quella parte dell'esempio con gli intervalli di punti di codice che desideri.

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))

Ecco una funzione di esempio che probabilmente crea una sequenza UTF-8 casuale ben formata, come definito nella Tabella 3-7 di 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)))

A causa della vastità dello standard Unicode, non riesco a verificarlo a fondo. Si noti inoltre che i caratteri non sono equamente distribuiti (ma ogni byte nella sequenza è).


Segue un codice che stampa qualsiasi carattere stampabile di UTF-8:

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

Tutti i personaggi sono presenti, anche quelli che non sono gestiti dal carattere usato. and not chr(l).isspace() può essere aggiunto per filtrare tutti i caratteri dello spazio. (compresa la scheda)


Dipende da quanto accuratamente vuoi fare i test e quanto accuratamente vuoi fare la generazione. Per intero, Unicode è un set di codici a 21 bit (U + 0000 .. U + 10FFFF). Tuttavia, alcuni pezzi piuttosto grandi di quella gamma sono riservati ai personaggi personalizzati. Vuoi preoccuparti di generare combinazioni di caratteri all'inizio di una stringa (perché dovrebbero apparire solo dopo un altro carattere)?

L'approccio di base che adotterei è generare casualmente un punto di codice Unicode (diciamo U + 2397 o U + 31232), validarlo nel contesto (è un carattere legittimo, può apparire qui nella stringa) e codificare punti di codice validi in UTF-8.

Se vuoi solo verificare se il tuo codice gestisce correttamente l'UTF-8 malformato, puoi usare schemi di generazione molto più semplici.

Nota che devi sapere cosa aspettarti dall'input, altrimenti non stai testando; stai sperimentando.





random