2012-10-11 15 views
18

Dưới đây là những gì tôi đang làmPython: Logging Lỗi Loại: không phải tất cả đối số được chuyển đổi trong chuỗi định dạng

>>> import logging 
>>> logging.getLogger().setLevel(logging.INFO) 
>>> from datetime import date 
>>> date = date.today() 
>>> logging.info('date={}', date) 
Traceback (most recent call last): 
    File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/logging/__init__.py", line 846, in emit 
    msg = self.format(record) 
    File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/logging/__init__.py", line 723, in format 
    return fmt.format(record) 
    File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/logging/__init__.py", line 464, in format 
    record.message = record.getMessage() 
    File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/logging/__init__.py", line 328, in getMessage 
    msg = msg % self.args 
TypeError: not all arguments converted during string formatting 
Logged from file <stdin>, line 1 
>>> 

phiên bản python của tôi là

$ python --version 
Python 2.7.3 

Làm thế nào để làm cho nó hoạt động?

Trả lời

10

Bạn có thể làm các định dạng bản thân:

logging.info('date={}'.format(date)) 

Như đã chỉ ra bởi Martijn Pieters, điều này sẽ luôn chạy định dạng chuỗi, trong khi sử dụng các module khai thác gỗ sẽ gây ra các định dạng chỉ được thực hiện nếu được thông báo thực sự được ghi lại.

+15

Đừng biết rằng bằng cách làm như định dạng chính mình, bạn mất lợi thế tốc độ được cung cấp bằng cách cho phép các module khai thác gỗ làm điều đó cho bạn * chỉ khi được thông báo là thực sự đã đăng nhập *. Nói cách khác, nếu bạn sử dụng trình xử lý 'debug()' nhưng mức ghi nhật ký không bao gồm mức DEBUG, bạn sẽ không phải chịu hình phạt của hoạt động định dạng chuỗi. Sự khác biệt tốc độ có thể là đáng kể nếu bạn có rất nhiều thông báo gỡ lỗi. –

32

Bạn không thể sử dụng định dạng kiểu mới khi sử dụng mô-đun ghi nhật ký; sử dụng %s thay vì {}.

logging.info('date=%s', date) 

Mô-đun ghi nhật ký sử dụng toán tử kiểu cũ % để định dạng chuỗi đăng nhập. Xem debug method để biết thêm chi tiết.

Nếu bạn thực sự muốn sử dụng str.format() chuỗi định dạng, xem xét sử dụng đối tượng tùy chỉnh mà áp dụng các định dạng 'muộn', khi thực sự chuyển đổi sang một chuỗi:

class BraceMessage(object): 
    def __init__(self, fmt, *args, **kwargs): 
     self.fmt = fmt 
     self.args = args 
     self.kwargs = kwargs 

    def __str__(self): 
     return self.fmt.format(*self.args, **self.kwargs) 

__ = BraceMessage 

logging.info(__('date={}', date)) 

Đây là một cách tiếp cận Python 3 logging module documentation proposes, và nó xảy ra để làm việc trên Python 2.

6

Câu trả lời của Martijn là chính xác, nhưng nếu bạn thích sử dụng định dạng kiểu mới với ghi nhật ký, nó có thể được thực hiện bằng cách phân lớp Logger.

import logging 

class LogRecord(logging.LogRecord): 
    def getMessage(self): 
     msg = self.msg 
     if self.args: 
      if isinstance(self.args, dict): 
       msg = msg.format(**self.args) 
      else: 
       msg = msg.format(*self.args) 
     return msg 

class Logger(logging.Logger): 
    def makeRecord(self, name, level, fn, lno, msg, args, exc_info, func=None, extra=None): 
     rv = LogRecord(name, level, fn, lno, msg, args, exc_info, func) 
     if extra is not None: 
      for key in extra: 
       rv.__dict__[key] = extra[key] 
     return rv 

Sau đó chỉ cần thiết lập các lớp logging:

logging.setLoggerClass(Logger) 
+0

Hoặc thậm chí (ít nhất là trên Python 3.5) chỉ sử dụng LogRecord với 'logging.setLogRecordFactory (LogRecord)' –

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