문제

최근에 오류 로깅 앱을 구축했으며 들어오는 데이터를 정확하게 타임 스탬프하는 방법 이후였습니다. 내가 정확하게 말할 때 나는 각 타임 스탬프가 서로에 대해 정확해야한다는 것을 의미합니다 (원자 시계 나 그와 비슷한 것과 동기화 할 필요는 없습니다).

DateTime.now ()를 첫 번째 찌르기로 사용했지만 완벽하지는 않습니다.

>>> for i in range(0,1000):
...     datetime.datetime.now()
...
datetime.datetime(2008, 10, 1, 13, 17, 27, 562000)
datetime.datetime(2008, 10, 1, 13, 17, 27, 562000)
datetime.datetime(2008, 10, 1, 13, 17, 27, 562000)
datetime.datetime(2008, 10, 1, 13, 17, 27, 562000)
datetime.datetime(2008, 10, 1, 13, 17, 27, 578000)
datetime.datetime(2008, 10, 1, 13, 17, 27, 578000)
datetime.datetime(2008, 10, 1, 13, 17, 27, 578000)
datetime.datetime(2008, 10, 1, 13, 17, 27, 578000)
datetime.datetime(2008, 10, 1, 13, 17, 27, 578000)
datetime.datetime(2008, 10, 1, 13, 17, 27, 609000)
datetime.datetime(2008, 10, 1, 13, 17, 27, 609000)
datetime.datetime(2008, 10, 1, 13, 17, 27, 609000)
etc.

첫 번째 샘플의 시계 사이의 변화는 다음과 같습니다.

uSecs    difference
562000  
578000  16000
609000  31000
625000  16000
640000  15000
656000  16000
687000  31000
703000  16000
718000  15000
750000  32000
765000  15000
781000  16000
796000  15000
828000  32000
843000  15000
859000  16000
890000  31000
906000  16000
921000  15000
937000  16000
968000  31000
984000  16000

따라서 타이머 데이터가 내 컴퓨터의 ~ 15-32ms마다 만 업데이트되는 것처럼 보입니다. 타임 스탬프 이외의 다른 것의 정렬을 한 다음 타임 스탬프로 정렬하면 데이터를 잘못된 순서 (연대순으로) 할 수 있기 때문에 문제는 데이터를 분석 할 때 발생합니다. 타임 스탬프 생성기에 대한 모든 호출이 고유 한 타임 스탬프를 제공하는 시점까지 타임 스탬프를 정확하게 만드는 것이 좋을 것입니다.

time.clock () 호출을 시작하는 데 필요한 몇 가지 방법을 고려하고 있었지만 동일한 기계의 스레드에서 정확하게 작동하는 솔루션에 감사 할 것입니다. 모든 제안은 매우 감사하게 접수 될 것입니다.

도움이 되었습니까?

해결책

중복 타임 스탬프의 가능성을 완전히 제거 할 수있는 충분히 세밀한 제어를 얻지 못할 것입니다. DateTime 객체를 생성하는 데 걸리는 시간보다 훨씬 작은 해상도가 필요합니다. 당신이 그것을 다루기 위해 취할 수있는 몇 가지 다른 접근법이 있습니다.

  1. 받아 들여. 타임 스탬프를 그대로 두지 말고 Python의 정렬에 의존하여 재정의 문제를 처리하기 위해 안정적입니다. 타임 스탬프 정렬 첫 번째, 그러면 다른 것이 타임 스탬프 순서를 유지합니다. 동일한 목록에서 여러 종류를 수행하지 않고 항상 타임 스탬프 주문 목록에서 항상 시작해야합니다.

  2. 독창성을 집행하기 위해 자신의 가치를 부여하십시오. 예를 들어. 키의 일부로 증분 정수 값을 포함 시키거나 타임 스탬프가 다른 경우에만 해당 값을 추가하십시오. 예를 들어.

다음은 고유 한 타임 스탬프 값을 보장합니다.

    class TimeStamper(object):
        def __init__(self):
            self.lock = threading.Lock()
            self.prev = None
            self.count = 0

         def getTimestamp(self):
             with self.lock:
                 ts = str(datetime.now())
                 if ts == self.prev:
                     ts +='.%04d' % self.count
                     self.count += 1
                 else:
                     self.prev = ts
                     self.count = 1
             return ts

스레드가 아닌 여러 프로세스의 경우 약간 까다로워집니다.

다른 팁

time.clock ()은 Windows의 WallClock 시간 만 측정합니다. 다른 시스템에서 Time.clock ()은 실제로 CPU 시간을 측정합니다. 해당 시스템에서 시간 ()은 월 클록 시간에 더 적합하며 Python이 관리 할 수있는만큼 높은 해상도가 있습니다. 이는 OS가 관리 할 수있는만큼 높습니다. 일반적으로 gettimeofday (3) (마이크로 초 분해능) 또는 ftime (3) (밀리 초 분해능)을 사용합니다. 다른 OS 제한은 실제로 실제 해상도를 그보다 훨씬 높게 만듭니다. dateTime.datetime.now ()는 time.time ()을 사용하므로 Time.Time ()은 직접 더 나을 수 없습니다.

레코드의 경우 루프에서 DateTime.dateTime.now ()를 사용하면 약 1/10000 초의 해상도가 표시됩니다. 데이터를 보면 그보다 훨씬 더 거친 해상도가 있습니다. Python이 할 수있는 일이 있는지 확실하지 않지만 OS가 다른 수단을 통해 더 잘 수행하도록 설득 할 수 있습니다.

Windows에서 Time.clock ()가 실제로 시간 (약간) 시간보다 정확하지만 시간에 대한 첫 번째 호출 이후 WallClock을 측정하는 것을 기억하는 것 같습니다. 따라서 초기화를 기억해야합니다. '먼저.

귀하의 기여에 감사드립니다. 모두 매우 유용합니다. Brian의 대답은 내가 결국 갔던 것과 가장 가까운 것 같습니다 (예 : 거래하지만 일종의 고유 식별자를 사용하십시오 - 아래 참조). 그래서 나는 그의 대답을 받아 들였다. 나는 모든 다양한 데이터 수신기를 단일 스레드로 통합 할 수있었습니다. AccurrateTimestamp 수업. 내가 한 일은 타임 스탬프가 시계를 사용하는 가장 먼저 사용되는 한 작동합니다.

S.Lott가 실시간 OS없이 규정함에 따라 절대적으로 완벽하지 않을 것입니다. 나는 실제로 들어오는 각 데이터 덩어리에 비해 볼 수있는 무언가를 원했습니다.

다시 한 번 감사드립니다!

import time

class AccurateTimeStamp():
    """
    A simple class to provide a very accurate means of time stamping some data
    """

    # Do the class-wide initial time stamp to synchronise calls to 
    # time.clock() to a single time stamp
    initialTimeStamp = time.time()+ time.clock()

    def __init__(self):
        """
        Constructor for the AccurateTimeStamp class.
        This makes a stamp based on the current time which should be more 
        accurate than anything you can get out of time.time().
        NOTE: This time stamp will only work if nothing has called clock() in
        this instance of the Python interpreter.
        """
        # Get the time since the first of call to time.clock()
        offset = time.clock()

        # Get the current (accurate) time
        currentTime = AccurateTimeStamp.initialTimeStamp+offset

        # Split the time into whole seconds and the portion after the fraction 
        self.accurateSeconds = int(currentTime)
        self.accuratePastSecond = currentTime - self.accurateSeconds


def GetAccurateTimeStampString(timestamp):
    """
    Function to produce a timestamp of the form "13:48:01.87123" representing 
    the time stamp 'timestamp'
    """
    # Get a struct_time representing the number of whole seconds since the 
    # epoch that we can use to format the time stamp
    wholeSecondsInTimeStamp = time.localtime(timestamp.accurateSeconds)

    # Convert the whole seconds and whatever fraction of a second comes after
    # into a couple of strings 
    wholeSecondsString = time.strftime("%H:%M:%S", wholeSecondsInTimeStamp)
    fractionAfterSecondString = str(int(timestamp.accuratePastSecond*1000000))

    # Return our shiny new accurate time stamp   
    return wholeSecondsString+"."+fractionAfterSecondString


if __name__ == '__main__':
    for i in range(0,500):
        timestamp = AccurateTimeStamp()
        print GetAccurateTimeStampString(timestamp)

"타임 스탬프는 서로에 비해 정확해야합니다."

왜 시간? 왜 시퀀스 번호가 아닌가? 클라이언트-서버 응용 프로그램의 클라이언트 인 경우 네트워크 대기 시간은 타임 스탬프를 무작위로 만듭니다.

외부 정보 소스와 일치하고 있습니까? 다른 응용 프로그램에 로그인을 말 하시겠습니까? 다시, 네트워크가 있다면, 그 시간은 너무 가깝지 않을 것입니다.

별도의 앱간에 물건을 일치시켜야하는 경우 두 앱이 GUID 값을 기록하도록 GUID를 통과하는 것을 고려하십시오. 그러면 타이밍 차이에 관계없이 그들이 일치하는 것이 절대적으로 확신 할 수 있습니다.

당신이 원한다면 상대적인 정확히 맞기 위해, 로거가받은 순서대로 각 메시지에 시퀀스 번호를 할당하기에 충분할 것입니다.

파이썬 타이밍 정확도에 대한 스레드는 다음과 같습니다.

python -time.clock () vs. time.time () - 정확도?

몇 년이 지난 후 몇 년이 지난 후 질문이 생겨 났으며, 이는 적어도 Windows의 Cpython에게 다루어졌습니다. Win7 64bit 및 Windows Server 2008 R2의 아래 스크립트를 사용하여 동일한 결과를 얻었습니다.

  • datetime.now() 1ms의 해상도와 1ms보다 작은 지터를 제공합니다.
  • time.clock() 1US보다 더 나은 해상도와 1ms보다 훨씬 작은 지터를 제공합니다.

대본 :

import time
import datetime

t1_0 = time.clock()
t2_0 = datetime.datetime.now()

with open('output.csv', 'w') as f:
    for i in xrange(100000):
        t1 = time.clock()
        t2 = datetime.datetime.now()
        td1 = t1-t1_0
        td2 = (t2-t2_0).total_seconds()
        f.write('%.6f,%.6f\n' % (td1, td2))

결과가 시각화되었습니다.enter image description here

이 마지막 게시물에 대해 J. Cage에게 감사하고 싶었습니다.

저의 작업에는 프로세스 및 플랫폼에서 이벤트의 "합리적인"타이밍이 필수적입니다. 일이 askew (시계 드리프트, 컨텍스트 전환 등)가 될 수있는 곳이 많지만,이 정확한 타이밍 솔루션은 기록 된 타임 스탬프가 다른 오류 소스를 볼 수있을 정도로 정확한지 확인하는 데 도움이 될 것이라고 생각합니다. .

즉, 내가 궁금해하는 몇 가지 세부 사항이 있습니다. 마이크로 초가 중요 할 때. 예를 들어, Time.Clock ()이 결국 랩을 할 것이라고 생각합니다. 나는 이것이 오랜 과정에서 작동하기 위해서는 그것을 처리해야 할 수도 있다고 생각합니다.

마이크로 초를 원한다면해결 (정확도가 아님) 파이썬의 타임 스탬프 창문, 내 대답에서 설명한대로 Windows의 QPC 타이머를 사용할 수 있습니다. 파이썬에서 밀리 초 및 마이크로 초해상 해상도 타임 스탬프를 얻는 방법. 아직 Linux 에서이 작업을 수행하는 방법을 잘 모르겠으므로 누군가가 알고 있다면 위의 링크에서 의견을 말하거나 답하십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top