2009-10-09 44 views
28

Tôi đang cố gắng ghi một chuỗi được mã hóa UTF-8 vào một tệp bằng gói ghi nhật ký của Python. Ví dụ về đồ chơi:UTF-8 Trong ghi nhật ký Python, làm cách nào?

import logging 

def logging_test(): 
    handler = logging.FileHandler("/home/ted/logfile.txt", "w", 
            encoding = "UTF-8") 
    formatter = logging.Formatter("%(message)s") 
    handler.setFormatter(formatter) 
    root_logger = logging.getLogger() 
    root_logger.addHandler(handler) 
    root_logger.setLevel(logging.INFO) 

    # This is an o with a hat on it. 
    byte_string = '\xc3\xb4' 
    unicode_string = unicode("\xc3\xb4", "utf-8") 

    print "printed unicode object: %s" % unicode_string 

    # Explode 
    root_logger.info(unicode_string) 

if __name__ == "__main__": 
    logging_test() 

Điều này phát ra với UnicodeDecodeError on the logging.info().

Ở cấp độ thấp hơn, gói ghi nhật ký của Python đang sử dụng gói codec để mở tệp nhật ký, chuyển trong đối số "UTF-8" làm mã hóa. Đó là tất cả tốt và tốt, nhưng nó đang cố gắng để viết chuỗi byte vào tập tin thay vì đối tượng unicode, mà phát nổ. Về cơ bản, Python được làm điều này:

file_handler.write(unicode_string.encode("UTF-8")) 

Khi nó nên làm điều này:

file_handler.write(unicode_string) 

Đây có phải là một lỗi trong Python, hoặc tôi đang uống thuốc điên? FWIW, đây là bản cài đặt Python 2.6.

+0

Mã của bạn làm việc hoàn toàn tốt đẹp ở đây . Tôi đã cố gắng để làm cho nó thất bại, nhưng tôi đã không thành công. –

+0

Và bạn nói đúng, python đang mã hóa nó với UTF-8, bởi vì nó hỏi outfile mã hóa nào để sử dụng, và bạn đã chỉ định UTF-8, vì vậy đó là tất cả và tốt. –

+1

Tôi phải nhấn máy quay lại để tìm [ví dụ] (http://web.archive.org/web/20100107060919/http://tony.czechit.net/2009/02/unicode-support-for-pythons -logging-library /) bạn đã đề cập. Hấp dẫn. – Epu

Trả lời

13

Kiểm tra xem bạn có phiên bản Python 2.6 mới nhất không - một số lỗi Unicode đã được tìm thấy và sửa chữa kể từ khi 2.6 xuất hiện. Ví dụ, trên hệ thống Ubuntu Jaunty của tôi, tôi chạy tập lệnh đã sao chép và dán, chỉ xóa tiền tố '/ home/ted /' từ tên tệp nhật ký. Kết quả (sao chép và dán từ một cửa sổ terminal):

 
[email protected]:~/projects/scratch$ python --version 
Python 2.6.2 
[email protected]:~/projects/scratch$ python utest.py 
printed unicode object: ô 
[email protected]:~/projects/scratch$ cat logfile.txt 
ô 
[email protected]:~/projects/scratch$ 

Trên một hộp Windows:

 
C:\temp>python --version 
Python 2.6.2 

C:\temp>python utest.py 
printed unicode object: ô 

Và các nội dung của file:

alt text

này cũng có thể giải thích tại sao Lennart Regebro cũng không thể tái tạo nó.

+0

Có phải đây là nó. Đã xảy ra lỗi trong gói nhật ký python đã được khắc phục trong phiên bản sau. –

+0

Tôi đang chạy Python 2.6.1 (r261: 67515, Feb 11 2010, 00:51:29) [GCC 4.2.1 (Apple Inc. xây dựng 5646)] trên darwin trên iMac của tôi và tôi vẫn gặp lỗi tương tự. Có phải lỗi thực sự đã được sửa chưa? – Tsf

+1

Có, nó đã xảy ra - giữa phiên bản 2.6.1 và 2.6.2, tại phiên bản 69448: http://svn.python.org/view?view=rev&revision=69448 - vì vậy bạn cần nâng cấp lên bản sửa đổi sau. –

1

Hãy thử điều này:

import logging 

def logging_test(): 
    log = open("./logfile.txt", "w") 
    handler = logging.StreamHandler(log) 
    formatter = logging.Formatter("%(message)s") 
    handler.setFormatter(formatter) 
    root_logger = logging.getLogger() 
    root_logger.addHandler(handler) 
    root_logger.setLevel(logging.INFO) 

    # This is an o with a hat on it. 
    byte_string = '\xc3\xb4' 
    unicode_string = unicode("\xc3\xb4", "utf-8") 

    print "printed unicode object: %s" % unicode_string 

    # Explode 
    root_logger.info(unicode_string.encode("utf8", "replace")) 


if __name__ == "__main__": 
    logging_test() 

Đối với những gì nó có giá trị tôi đã mong đợi phải sử dụng codecs.open để mở tập tin với utf-8 mã hóa nhưng một trong hai đó là mặc định hay cái gì khác đang xảy ra ở đây, vì nó hoạt động như thế này.

+0

NameError: tên toàn cục 'unicode' không được xác định – Gank

+0

@Gank bạn đang sử dụng python 3 Tôi đoán – warvariuc

1

Nếu tôi hiểu vấn đề của bạn một cách chính xác, cùng một vấn đề nên phát sinh trên hệ thống của bạn khi bạn làm chỉ:

str(u'ô') 

Tôi đoán mã hóa tự động để mã hóa bản địa trên Unix sẽ không hoạt động cho đến khi bạn đã kích hoạt locale- nhận biết chi nhánh if ở hàm setencoding trong mô-đun site của bạn qua locale. Tệp này thường nằm trong /usr/lib/python2.x, nó đáng để kiểm tra. AFAIK, locale-aware setencoding bị tắt theo mặc định (nó đúng với cài đặt Python 2.6 của tôi).

Các lựa chọn là:

  • Hãy để con số hệ thống ra đúng cách để mã hóa chuỗi Unicode để byte hoặc làm điều đó trong mã của bạn (một số cấu hình trong trang web cụ thể site.py là cần thiết)
  • Mã hóa Unicode các chuỗi trong mã của bạn và đầu ra chỉ là các byte

Xem thêm The Illusive setdefaultencoding bởi Ian Bicking và các liên kết liên quan.

21

Có mã như:

raise Exception(u'щ') 

gây ra:

File "/usr/lib/python2.7/logging/__init__.py", line 467, in format 
    s = self._fmt % record.__dict__ 
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3: ordinal not in range(128) 

Điều này xảy ra bởi vì các chuỗi định dạng là một chuỗi byte, trong khi một số các đối số chuỗi định dạng là chuỗi unicode với các ký tự ASCII :

>>> "%(message)s" % {'message': Exception(u'\u0449')} 
*** UnicodeEncodeError: 'ascii' codec can't encode character u'\u0449' in position 0: ordinal not in range(128) 

Làm cho chuỗi định dạng unicode khắc phục sự cố:

>>> u"%(message)s" % {'message': Exception(u'\u0449')} 
u'\u0449' 

Vì vậy, trong cấu hình đăng nhập của bạn làm cho tất cả chuỗi định dạng unicode:

'formatters': { 
    'simple': { 
     'format': u'%(asctime)-s %(levelname)s [%(name)s]: %(message)s', 
     'datefmt': '%Y-%m-%d %H:%M:%S', 
    }, 
... 

Và vá mặc định logging định dạng để sử dụng chuỗi định dạng unicode:

logging._defaultFormatter = logging.Formatter(u"%(message)s") 
+1

Điều gì về Python 3.5? Không phải tất cả các chuỗi là một unicode theo mặc định? –

+0

@JanuszSkonieczny bạn có cùng vấn đề với Python 3 – warvariuc

+0

Có phải tôi đã làm trong vùng chứa docker. Tôi giải quyết nó bằng cách thiết lập một loạt các biến env kết nối với mã hóa os. Đối với bất kỳ ai vấp ngã ở đây với cùng một vấn đề, hãy xem http://stackoverflow.com/a/27931669/260480. –

Các vấn đề liên quan