2009-07-30 14 views
45

Tôi muốn ghi lại thời gian sử dụng trong thời gian thực. Hiện tại tôi đang thực hiện việc này:Làm thế nào để có được thời lượng đơn điệu trong python?

startTime = time.time() 
someSQLOrSomething() 
print "That took %.3f seconds" % (time.time() - startTime) 

Nhưng điều đó sẽ không thành công (tạo kết quả không chính xác) nếu thời gian được điều chỉnh trong khi truy vấn SQL đang chạy.

Tôi không muốn chỉ chuẩn nó. Tôi muốn đăng nhập nó trong một ứng dụng trực tiếp để xem xu hướng trên một hệ thống trực tiếp.

Tôi muốn một cái gì đó như clock_gettime (CLOCK_MONOTONIC, ...), nhưng bằng Python. Và tốt nhất là không cần phải viết một mô-đun C gọi clock_gettime().

+6

Vâng, tôi thật sự không biết làm thế nào thường nó thực sự được điều chỉnh. Tôi chạy NTP. Nhưng với một đồng hồ đơn điệu, tôi sẽ không phải chạy vào những thứ như lỗi Oracle RAC mà nó khởi động lại hệ thống nếu thời gian được thiết lập ngược. Bên cạnh các điều chỉnh NTP nhỏ, có những giây nhảy vọt có thể quay lại và tiến lên. – Thomas

+7

S.Lott: không đúng. "Một bước nhảy vọt thứ hai là một điều chỉnh tích cực hoặc tiêu cực trong một giây [...]". Nó tầm thường để nhìn lên. Đây là câu đầu tiên trong bài viết "Leap second" trên Wikipedia. Vì vậy, khi một giây nhảy vọt được thêm vào, NTP sẽ điều chỉnh lại thời gian hệ thống của bạn ngược lại (bởi vì hệ thống của bạn nhanh. Nó không tính 23:59:60), có nghĩa là một phép đo dựa trên time.time() có thể âm. Tôi tin tưởng, nhiều máy chủ Oracle khởi động lại do lỗi mà tôi đã đề cập ở trên các newyears mới nhất. Và tôi chỉ sử dụng Oracle làm ví dụ trong đó một số chương trình không thể xử lý các điều chỉnh thời gian. – Thomas

+0

Tôi không biết tại sao (chưa được vá) Oracle 10 thực hiện điều đó. Nó chỉ làm, và Oracle (công ty) xác nhận nó. – Thomas

Trả lời

71

Đó là chức năng rất đơn giản đủ mà bạn có thể sử dụng ctypes để truy cập nó:

#!/usr/bin/env python 

__all__ = ["monotonic_time"] 

import ctypes, os 

CLOCK_MONOTONIC_RAW = 4 # see <linux/time.h> 

class timespec(ctypes.Structure): 
    _fields_ = [ 
     ('tv_sec', ctypes.c_long), 
     ('tv_nsec', ctypes.c_long) 
    ] 

librt = ctypes.CDLL('librt.so.1', use_errno=True) 
clock_gettime = librt.clock_gettime 
clock_gettime.argtypes = [ctypes.c_int, ctypes.POINTER(timespec)] 

def monotonic_time(): 
    t = timespec() 
    if clock_gettime(CLOCK_MONOTONIC_RAW , ctypes.pointer(t)) != 0: 
     errno_ = ctypes.get_errno() 
     raise OSError(errno_, os.strerror(errno_)) 
    return t.tv_sec + t.tv_nsec * 1e-9 

if __name__ == "__main__": 
    print monotonic_time() 
+0

Chà. Xóa "tự". và nó hoạt động hoàn hảo. Rất ấn tượng. Nó đòi hỏi ctypes là add-on cho Python 2.4, nhưng nó sẽ làm khá độc đáo. Cảm ơn. – Thomas

+0

Ồ, và CLOCK_MONOTONIC dường như là 4 trên FreeBSD và 1 trên Linux. – Thomas

+0

Giải pháp tốt. Có lý do nào bạn sử dụng ctypes.pointer thay vì ctypes.byref không? – Kiv

8

Như đã chỉ ra trong this question, tránh điều chỉnh NTP trên Linux đòi hỏi CLOCK_MONOTONIC_RAW. Nó được định nghĩa là 4 trên Linux (kể từ 2.6.28).

Có thể nhận được hằng số chính xáC#defined trong tiêu đề C từ Python là khó khăn; có h2py, nhưng điều đó không thực sự giúp bạn có được giá trị khi chạy.

+1

Tôi tin câu trả lời đã chọn không chính xác và không giải thích nhảy, xem [bình luận của tôi về nó] (http://stackoverflow.com/questions/3657289/linux-clock-gettimeclock-monotonic-strange-non-monotonic-behavior#comment12057005_3657385). Cả hai CLOCK_MONOTONIC và CLOCK_MONOTONIC_RAW đều đơn điệu, và cách duy nhất chúng khác nhau là trước đây sửa chữa tốc độ đồng hồ phần cứng bằng NTP. – Tobu

23

Bây giờ, trong Python 3.3 bạn sẽ sử dụng time.monotonic.

+0

Trong CPython, tôi giả sử điều này sử dụng nội bộ 'CLOCK_MONOTONIC' và ** không **' CLOCK_MONOTONIC_RAW', với sau này thậm chí không có sẵn trong Python 3.3. –

+0

@ABB: ['time' module biết về' CLOCK_MONOTONIC_RAW'] (http://hg.python.org/cpython/file/e20f98a8ed71/Modules/timemodule.c#l1377) mặc dù nó không sử dụng nó như xa như Tôi có thể nhìn thấy. Bạn có thể [định nghĩa đồng hồ sử dụng nó thông qua 'ctypes' ngay cả trên Python 2.7] (https://gist.github.com/zed/5073409) – jfs

+0

Nếu tôi đọc tài liệu đúng, có vẻ như trong Python 3.3 bạn có thể nhận được 'CLOCK_MONOTONIC_RAW' bằng cách gọi' time.clock_gettime (time.CLOCK_MONOTONIC_RAW) ', rất tuyệt vời khi bạn sử dụng nó để đo khoảng thời gian nhỏ mà bạn không bao giờ gặp lỗi khi mạng cập nhật thời gian qua điều chỉnh NTP (Network Time Protocol). Tham chiếu thời gian Python: https://docs.python.org/3/library/time.html#time.CLOCK_MONOTONIC_RAW. <- LƯU Ý: CHỈ dành cho UNIX/LINUX ONLY. Đối với Windows, chỉ cần gọi 'time.clock()', đã có độ phân giải micro giây hoặc tốt hơn vì nó sử dụng QueryPerformanceCounter(). –

0

time.monotonic() có thể có ích:

Return giá trị (tính bằng giây phân đoạn) của một chiếc đồng hồ đơn điệu, ví dụ: một chiếc đồng hồ mà không thể đi lùi. Đồng hồ không bị ảnh hưởng bởi các bản cập nhật đồng hồ hệ thống. Điểm tham chiếu của giá trị trả về là không xác định, do đó chỉ có sự khác biệt giữa kết quả của các cuộc gọi liên tiếp là hợp lệ.

1

Đây là cách tôi có được thời gian đơn điệu bằng Python 2.7:

Cài đặt monotonic gói:

pip install monotonic 

Sau đó, trong Python:

import monotonic; mtime = monotonic.time.time #now mtime() can be used in place of time.time() 

t0 = mtime() 
#...do something 
elapsed = mtime()-t0 #gives correct elapsed time, even if system clock changed. 
Các vấn đề liên quan