سؤال

لقد قمت مؤخرًا بإنشاء تطبيق لتسجيل الأخطاء وكنت أبحث عن طريقة لتحديد الطابع الزمني للبيانات الواردة بدقة.عندما أقول بدقة، أعني أن كل طابع زمني يجب أن يكون دقيقًا بالنسبة لبعضه البعض (لا حاجة للمزامنة مع ساعة ذرية أو أي شيء من هذا القبيل).

لقد كنت أستخدم 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-32 مللي ثانية على جهازي.تأتي المشكلة عندما نأتي لتحليل البيانات لأن الفرز حسب شيء آخر غير الطابع الزمني ثم الفرز حسب الطابع الزمني مرة أخرى يمكن أن يترك البيانات في ترتيب خاطئ (ترتيبًا زمنيًا).سيكون من الجيد أن تكون الطوابع الزمنية دقيقة لدرجة أن أي اتصال بمولد الطابع الزمني يعطي طابعًا زمنيًا فريدًا.

كنت أفكر في بعض الطرق التي تتضمن استخدام استدعاء time.clock()‎ الذي تمت إضافته إلى وقت وتاريخ البدء، ولكني سأقدر الحل الذي من شأنه أن يعمل بدقة عبر سلاسل العمليات على نفس الجهاز.وسيتم تلقي أي اقتراحات في غاية الامتنان.

هل كانت مفيدة؟

المحلول

من غير المرجح أن تحصل على تحكم في الحبيبات الدقيقة بما فيه الكفاية بحيث يمكنك القضاء تمامًا على إمكانية الزمن الزمني المكررة - ستحتاج إلى دقة أصغر من الوقت الذي يستغرقه إنشاء كائن DateTime.هناك طريقتان أخريان يمكنك اتباعهما للتعامل معه:

  1. تعامل مع.اترك الطوابع الزمنية الخاصة بك غير فريدة كما هي، ولكن اعتمد على كون نوع بايثون مستقرًا للتعامل مع مشكلات إعادة الترتيب.الفرز على الطابع الزمني أولاً, ، فسيحتفظ شيء آخر بترتيب الطابع الزمني - عليك فقط أن تكون حريصًا على البدء دائمًا من القائمة المطلوبة للطوابع الزمنية في كل مرة، بدلاً من إجراء عمليات فرز متعددة في نفس القائمة.

  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 () يقيس فقط وقت wallclock على ويندوز. على أنظمة أخرى، time.clock () فعلا يقيس CPU-الوقت. على تلك الأنظمة time.time () هو أكثر ملاءمة للمرة wallclock، ولها يصل الى قرار في بيثون يمكن إدارة - وهو معدل مرتفع مثل OS يمكن إدارة. وعادة ما تستخدم gettimeofday (3) (القرار ميكروثانية) أو ftime (3) (القرار ميلي ثانية واحدة.) القيود OS أخرى في الواقع جعل القرار الحقيقي أعلى من ذلك بكثير. datetime.datetime.now () يستخدم time.time ()، لذلك time.time () ومباشرة لا يكون أفضل.

لسجل، إذا كنت تستخدم datetime.datetime.now () في حلقة، وأرى حول قرار ثان 1/10000. من النظر إلى البيانات الخاصة بك، لديك الكثير، القرار خشونة من ذلك بكثير. لست متأكدا ما إذا كان هناك أي شيء بيثون على هذا النحو يمكن القيام به، على الرغم من أنك قد تكون قادرة على إقناع نظام التشغيل لنفعل ما هو أفضل من خلال وسائل أخرى.

ويبدو لي أن أذكر أن على ويندوز، time.clock () هو في الواقع (قليلا) أكثر دقة من time.time ()، لكنه يقيس wallclock منذ الدعوة الأولى لtime.clock ()، لذلك عليك أن تتذكر إلى "تهيئة" لأول مرة.

شكرًا لكم جميعًا على مساهماتكم - لقد كانت جميعها مفيدة جدًا.تبدو إجابة براين هي الأقرب إلى ما ذهبت إليه في النهاية (أي.تعامل معها ولكن استخدم نوعًا من المعرف الفريد - انظر أدناه) لذلك قبلت إجابته.لقد تمكنت من دمج جميع أجهزة استقبال البيانات المختلفة في سلسلة رسائل واحدة حيث يتم الآن إجراء الطابع الزمني باستخدام ملفي الجديد الطابع الزمني الدقيق فصل.ما قمت به يعمل طالما أن الطابع الزمني هو أول شيء يستخدم الساعة.

كما تنص S.Lott، بدون نظام تشغيل حقيقي، فإنها لن تكون مثالية تمامًا.أردت حقًا فقط شيئًا يسمح لي برؤية ما يتعلق بكل جزء من البيانات الواردة، ومتى تم استلام الأشياء، لذا فإن ما لدي أدناه سيعمل بشكل جيد.

شكرا مرة أخرى للجميع!

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).ومن ثم يمكنك التأكد تمامًا من تطابقهما، بغض النظر عن اختلافات التوقيت.

إذا كنت تريد نسبي لكي تكون صحيحًا تمامًا، ربما يكفي أن يقوم المسجل الخاص بك بتعيين رقم تسلسلي لكل رسالة بالترتيب الذي تم استلامها به.

وهنا هو موضوع حول بيثون دقة توقيت:

- time.clock () مقابل time.time () - دقة <؟ / P>

لقد مضت بضع سنوات منذ أن تم طرح السؤال والإجابة عليه، وتم التعامل مع هذا الأمر، على الأقل بالنسبة لـ CPython على نظام التشغيل Windows.باستخدام البرنامج النصي أدناه على كل من Win7 64bit وWindows Server 2008 R2، حصلت على نفس النتائج:

  • datetime.now() يعطي دقة تبلغ 1 مللي ثانية وارتعاشًا أصغر من 1 مللي ثانية
  • 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. قفص لهذا المنصب الماضية.

لعملي، "معقول" توقيت الأحداث عبر العمليات ومنصات أمر ضروري. ومن الواضح أن هناك الكثير من الأماكن التي يمكن أن تسير الأمور منحرف (الانجراف على مدار الساعة، والتحول السياق، وما إلى ذلك)، ولكن هذا الحل توقيت دقيق، كما أعتقد، أن تساعد على ضمان الطوابع الوقت المسجل دقيقة بما فيه الكفاية لمعرفة مصادر أخرى للخطأ .

وقال ان هناك عددا من التفاصيل وأتساءل عن ذلك سيتم شرحها في <لأ href = "http://www.ibm.com/developerworks/library/i-seconds/" يختلط = "نوفولو noreferrer" عنوان = وقال "عندما ميكروثانية المسألة"> عندما ميكروثانية المسألة . على سبيل المثال، وأعتقد أن time.clock () التفاف في نهاية المطاف. وأعتقد أن لهذا العمل لعملية تشغيل طويلة، قد يكون لديك للتعامل مع ذلك.

إذا كنت تريد microsecond- <م> قرار (NOT دقة) الطوابع الزمنية في بيثون، في النوافذ و يمكنك استخدام QPC الموقت ويندوز، وكما هو موضح في جوابي هنا: <ل أ href = "https://stackoverflow.com/questions/38319606/how-to-get-millisecond-and-microsecond-resolution-timestamps-in-python"> كيفية الحصول على ميلي ثانية واحدة وميكروثانية الدقة الطوابع في بيثون . لست متأكدا من كيفية القيام بذلك في لينكس بعد، لذلك إذا كان أي شخص يعرف، يرجى التعليق أو الإجابة في الرابط أعلاه.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top