2009-09-25 54 views
18

Tôi muốn kiểm tra việc xử lý mã Unicode của tôi. Có bất cứ điều gì tôi có thể đặt trong random.choice() để chọn từ toàn bộ phạm vi Unicode, tốt nhất không phải là một mô-đun bên ngoài? Google hoặc StackOverflow dường như không có câu trả lời.Tạo chuỗi UTF-8 ngẫu nhiên trong Python

Chỉnh sửa: Có vẻ như điều này phức tạp hơn dự kiến, vì vậy tôi sẽ thuật lại câu hỏi - Mã sau có đủ để tạo tất cả non-control characters in Unicode hợp lệ không?

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

Điều này có thể hữu ích nếu bạn cung cấp thêm chi tiết về "kiểm tra xử lý mã Unicode của tôi" và giải thích phần tạo chuỗi UTF-8 ngẫu nhiên là gì trong thử nghiệm đó và bạn coi là "toàn bộ phạm vi Unicode" (16 bit? 21 bit? không thay thế mã-điểm? chars hợp lệ (ví dụ không phải U + FFFF)?). Bạn có tin cậy bộ mã hóa Python UTF-8 hay bạn cũng cần kiểm tra nó? Python 2.X hoặc 3.X hoặc cả hai? –

+1

Mục tiêu là chấp nhận bất kỳ điểm mã Unicode (ký tự) có thể in, hợp lệ nào làm đầu vào cho giao diện web bằng Python 2.6. – l0b0

Trả lời

7

Có một UTF-8 stress test from Markus Kuhn bạn có thể sử dụng.

Xem thêm Really Good, Bad UTF-8 example test data.

+0

Điều đó sẽ hữu ích để đảm bảo rằng chương trình không phá vỡ khi được đưa ra văn bản không chính xác, nhưng nó sẽ không giúp đỡ như một thử nghiệm comformance. – voyager

+0

+1. l0b0: đừng lo lắng về việc tạo ra unicode ngẫu nhiên. Vay bánh xe của người khác> phát minh lại nó. –

+3

Câu trả lời hay, nhưng không thực sự trả lời câu hỏi theo yêu cầu. – Kylotan

0

Vì Unicode chỉ là một loạt các mã tốt, nên sử dụng unichr() để nhận chuỗi unicode tương ứng với số ngẫu nhiên từ 0 đến 0xFFFF?
(Tất nhiên sẽ chỉ cung cấp một điểm duy nhất, vì vậy hãy lặp lại theo yêu cầu)

+3

Thật không may, nó không đơn giản như vậy. Unicode chứa nhiều hơn 0x100000 ký tự và phạm vi không được kết nối. Ví dụ: các giá trị thay thế không bao giờ xuất hiện dưới dạng các điểm mã đơn lẻ. Vì vậy, các câu hỏi về những gì tạo thành một chuỗi UTF-8 hợp lệ là rất nontrivial. Các chi tiết được mô tả trong định nghĩa D92 của Chương 3 của Tiêu chuẩn Unicode. Ngoài ra còn có một bảng (3–7)) liệt kê tất cả các khả năng hợp lệ cho các chuỗi byte UTF-8. – Philipp

+0

Tôi hiểu, cảm ơn :) – Joril

+0

Unicode chạy từ U + 0000 đến U + 10FFFF; cũng có rất nhiều điểm mã không hợp lệ, kể cả (khi nó xảy ra) U + FFFF. Tiêu chuẩn Unicode nói về nó " - giá trị FFFF được đảm bảo không phải là một ký tự Unicode ở tất cả". –

0

Bạn có thể tải xuống trang web bằng tiếng Hy Lạp hoặc tiếng Đức sử dụng unicode và nguồn cấp dữ liệu đó cho mã của bạn.

3

Tùy thuộc vào mức độ kỹ lưỡng mà bạn muốn thực hiện thử nghiệm và mức độ chính xác mà bạn muốn thực hiện. Đầy đủ, Unicode là bộ mã 21 bit (U + 0000 .. U + 10FFFF). Tuy nhiên, một số phần khá lớn của phạm vi đó được dành riêng cho các ký tự tùy chỉnh. Bạn có muốn lo lắng về việc tạo các ký tự kết hợp ở đầu chuỗi không (vì chúng chỉ xuất hiện sau một ký tự khác)?

Cách tiếp cận cơ bản tôi muốn áp dụng là tạo mã Unicode ngẫu nhiên (nói U + 2397 hoặc U + 31232), xác thực trong ngữ cảnh (có phải là ký tự hợp pháp; nó có thể xuất hiện ở đây trong chuỗi) và mã hóa hay không các điểm mã hợp lệ trong UTF-8.

Nếu bạn chỉ muốn kiểm tra xem mã của bạn có xử lý đúng UTF-8 không chính xác không, bạn có thể sử dụng nhiều lược đồ thế hệ đơn giản hơn nhiều.

Lưu ý rằng bạn cần phải biết những gì mong đợi cho đầu vào - nếu không bạn không thử nghiệm; bạn đang thử nghiệm.

7

Dưới đây là một chức năng ví dụ mà có thể tạo ra một tốt được hình thành chuỗi UTF-8 ngẫu nhiên, theo quy định tại Bảng 3-7 của 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))) 

Bởi vì sự rộng lớn của các tiêu chuẩn Unicode Tôi không thể kiểm tra kỹ lưỡng. Cũng lưu ý rằng các ký tự không phân bố đều nhau (nhưng mỗi byte trong chuỗi là).

0

Trả lời câu hỏi điều chỉnh:

Vâng, trên một định nghĩa chặt chẽ của "ký tự điều khiển" - lưu ý rằng bạn sẽ không bao gồm CR, LF, và TAB; đó là điều bạn muốn?

Vui lòng xem xét trả lời lời mời trước đó của tôi để cho chúng tôi biết bạn đang thực sự cố gắng làm gì.

10

Mọi người có thể tìm đường đến đây dựa chủ yếu vào tiêu đề câu hỏi, vì vậy đây là cách để tạo chuỗi ngẫu nhiên chứa nhiều ký tự Unicode. Để bao gồm nhiều hơn (hoặc ít hơn) ký tự có thể, chỉ cần mở rộng một phần của ví dụ với các phạm vi điểm mã mà bạn muốn.

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

Cảm ơn, Jacob. Có bất kỳ vấn đề nào trong việc chạy mã này trong Python 2.7 không? – morfys

+1

@morfys Nó không có, nhưng tôi chỉ chỉnh sửa nó để nó. Cam ơn vi đa hỏi. –

+0

Cảm ơn rất nhiều, Jacob! – morfys

2

Làm theo một mã mà in bất kỳ ký tự in của UTF-8:

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

Tất cả các nhân vật có mặt, ngay cả những người không được xử lý bởi các font sử dụng. and not chr(l).isspace() có thể được thêm vào để lọc ra tất cả các ký tự khoảng trắng. (bao gồm cả tab)

+0

Đó không phải là thực sự sẽ cung cấp cho bạn một chuỗi ngẫu nhiên, mặc dù tất nhiên bạn chỉ có thể sử dụng ['random.sample'] (https://docs.python.org/2/library/random.html#random.sample) để thay thế của 'in'. – l0b0

+0

'random.sample' không thay thế các mục đã vẽ. –

+0

Vì vậy, hãy sử dụng 'random.choices' để thay thế. – gimboland