verimli dairesel tampon?


109

Python'da verimli bir dairesel tampon oluşturmak istiyorum ( tampondaki tamsayı değerlerinin ortalamalarını almak amacıyla).

Bu, değerleri toplamak için bir listeyi kullanmanın etkili bir yolu mu?

def add_to_buffer( self, num ):
    self.mylist.pop( 0 )
    self.mylist.append( num )

Hangisi daha verimli olabilir (ve neden)?


Bu, döngüsel arabelleği uygulamanın verimli bir yolu değildir çünkü pop (0), listedeki O (n) işlemidir. pop (0) listedeki ilk öğeyi kaldırır ve tüm öğelerin sola kaydırılması gerekir. Bunun yerine, maxlen özniteliğiyle collections.deque kullanın. deque, ekleme ve açma için O (1) işlemine sahiptir.
Vlad Bezden

Yanıtlar:


205

Arg collections.dequeile kullanırdımmaxlen

>>> import collections
>>> d = collections.deque(maxlen=10)
>>> d
deque([], maxlen=10)
>>> for i in xrange(20):
...     d.append(i)
... 
>>> d
deque([10, 11, 12, 13, 14, 15, 16, 17, 18, 19], maxlen=10)

Dokümanlarda bunun istediğinize benzer bir tarif var deque. Bunun en verimli olduğu iddiam, tamamen birinci sınıf kodu çalıştırma alışkanlığı olan inanılmaz derecede yetenekli bir ekip tarafından C'ye uygulandığı gerçeğine dayanıyor.


7
+1 Evet, pillerin dahil olduğu güzel bir yol. Dairesel arabellek için işlemler O (1) ve dediğiniz gibi, fazladan ek yük C cinsinden, bu yüzden hala oldukça hızlı olmalı
John La Rooy

7
Bu çözümü sevmiyorum çünkü dokümanlar maxlentanımlandığında O (1) rasgele erişimi garanti etmiyor . O (n), dequecan sonsuza kadar büyüdüğünde anlaşılabilir , ancak maxlenverilirse, bir elemanın indekslenmesi sabit zaman olmalıdır.
lvella

1
Tahminimce bir dizi olarak değil bağlantılı bir liste olarak uygulandı.
e-satis

1
Aşağıdaki cevabımdaki zamanlamalar doğruysa doğru görünüyor.
djvg

13

bir listenin başından çıkmak tüm listenin kopyalanmasına neden olur, dolayısıyla verimsizdir

Bunun yerine sabit boyutlu bir liste / dizi ve öğeleri eklerken / kaldırırken arabellekte hareket eden bir dizin kullanmalısınız.


4
Katılıyorum. Ne kadar zarif ya da zarif görünse de ya da hangi dil kullanılırsa kullanılsın. Gerçekte, çöp toplayıcıyı (veya yığın yöneticisini veya sayfalama / eşleme mekanizmalarını veya gerçek bellek büyüsünü yapan her şeyi) ne kadar az rahatsız ederseniz, o kadar iyidir.

@RocketSurgeon Bu sihir değil, sadece ilk elemanı silinen bir dizi. Yani n boyutundaki bir dizi için bu, n-1 kopyalama işlemleri anlamına gelir. Buraya çöp toplayıcı veya benzeri bir cihaz dahil değildir.
Christian

3
Katılıyorum. Bunu yapmak da bazılarının düşündüğünden çok daha kolaydır. Sadece sürekli artan bir sayaç kullanın ve öğeye erişirken modulo operatörünü (% arraylen) kullanın.
Andre Blum

idem, yukarıdaki
yazımı

10

Dayanarak MoonCactus cevabı , burada olduğu circularlistsınıf. Onun sürümünden farkı, burada c[0]her zaman en eski eklenen öğeyi, c[-1]en son eklenen öğeyi, c[-2]sondan bir önceki öğeyi vermesidir ... Bu, uygulamalar için daha doğaldır.

c = circularlist(4)
c.append(1); print c, c[0], c[-1]    #[1]              1, 1
c.append(2); print c, c[0], c[-1]    #[1, 2]           1, 2
c.append(3); print c, c[0], c[-1]    #[1, 2, 3]        1, 3
c.append(8); print c, c[0], c[-1]    #[1, 2, 3, 8]     1, 8
c.append(10); print c, c[0], c[-1]   #[10, 2, 3, 8]    2, 10
c.append(11); print c, c[0], c[-1]   #[10, 11, 3, 8]   3, 11

Sınıf:

class circularlist(object):
    def __init__(self, size, data = []):
        """Initialization"""
        self.index = 0
        self.size = size
        self._data = list(data)[-size:]

    def append(self, value):
        """Append an element"""
        if len(self._data) == self.size:
            self._data[self.index] = value
        else:
            self._data.append(value)
        self.index = (self.index + 1) % self.size

    def __getitem__(self, key):
        """Get element by index, relative to the current index"""
        if len(self._data) == self.size:
            return(self._data[(key + self.index) % self.size])
        else:
            return(self._data[key])

    def __repr__(self):
        """Return string representation"""
        return self._data.__repr__() + ' (' + str(len(self._data))+' items)'

[Düzenlendi]:data Mevcut listelerden başlatmaya izin vermek için isteğe bağlı parametre eklendi , örneğin:

circularlist(4, [1, 2, 3, 4, 5])      #  [2, 3, 4, 5] (4 items)
circularlist(4, set([1, 2, 3, 4, 5])) #  [2, 3, 4, 5] (4 items)
circularlist(4, (1, 2, 3, 4, 5))      #  [2, 3, 4, 5] (4 items)

İyi bir ek. Python listeleri zaten negatif indekslere izin verir, ancak (-1), örneğin listeye "son" ekleme listenin içinde sona erdiği için döngüsel tampon dolduğunda beklenen değeri döndürmez .
MoonCactus

1
@ MoonCactus işe yarıyor, cevabın üstünde verdiğim 6 örneğe bakın; sonuncularda c[-1], her zaman doğru unsur olduğunu görebilirsiniz. __getitem__doğru mu?
2018, 08:24 Basj

oh evet, yani benimki başarısız oldu, senin değil, üzgünüm: DI yorumumu daha net hale getirecek! - Yapamam, yorum çok eski.
MoonCactus

güzel, basit bir çözüm. Listenin mevcut verilerden başlatılmasına izin vermek için isteğe bağlı bir argüman ekledim, bu şekilde daha fazla pythonpathetic.
Orwellophile

9

Python'un sesi yavaştır. Bunun yerine numpy.roll da kullanabilirsiniz. Numpy bir şekil dizisindeki (n,) veya (n, 1) sayıları nasıl döndürürsünüz?

Bu kıyaslamada deque 448ms'dir. Numpy.roll 29 ms'dir http://scimusing.wordpress.com/2013/10/25/ring-buffers-in-pythonnumpy/


1
Ama numpy.rolldizinin bir kopyasını döndürür, değil mi?
djvg

3
Bu cevap çok yanıltıcıdır - Python'un sekmesi oldukça hızlı görünmektedir, ancak uyuşuk dizilerden ve dizilere dönüştürme, bağladığınız kıyaslamalarda onu önemli ölçüde yavaşlatır.
xitrium

7

Tamam deque sınıfının kullanımıyla tamam, ancak sorunun talepleri için (ortalama) bu benim çözümüm:

>>> from collections import deque
>>> class CircularBuffer(deque):
...     def __init__(self, size=0):
...             super(CircularBuffer, self).__init__(maxlen=size)
...     @property
...     def average(self):  # TODO: Make type check for integer or floats
...             return sum(self)/len(self)
...
>>>
>>> cb = CircularBuffer(size=10)
>>> for i in range(20):
...     cb.append(i)
...     print "@%s, Average: %s" % (cb, cb.average)
...
@deque([0], maxlen=10), Average: 0
@deque([0, 1], maxlen=10), Average: 0
@deque([0, 1, 2], maxlen=10), Average: 1
@deque([0, 1, 2, 3], maxlen=10), Average: 1
@deque([0, 1, 2, 3, 4], maxlen=10), Average: 2
@deque([0, 1, 2, 3, 4, 5], maxlen=10), Average: 2
@deque([0, 1, 2, 3, 4, 5, 6], maxlen=10), Average: 3
@deque([0, 1, 2, 3, 4, 5, 6, 7], maxlen=10), Average: 3
@deque([0, 1, 2, 3, 4, 5, 6, 7, 8], maxlen=10), Average: 4
@deque([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], maxlen=10), Average: 4
@deque([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], maxlen=10), Average: 5
@deque([2, 3, 4, 5, 6, 7, 8, 9, 10, 11], maxlen=10), Average: 6
@deque([3, 4, 5, 6, 7, 8, 9, 10, 11, 12], maxlen=10), Average: 7
@deque([4, 5, 6, 7, 8, 9, 10, 11, 12, 13], maxlen=10), Average: 8
@deque([5, 6, 7, 8, 9, 10, 11, 12, 13, 14], maxlen=10), Average: 9
@deque([6, 7, 8, 9, 10, 11, 12, 13, 14, 15], maxlen=10), Average: 10
@deque([7, 8, 9, 10, 11, 12, 13, 14, 15, 16], maxlen=10), Average: 11
@deque([8, 9, 10, 11, 12, 13, 14, 15, 16, 17], maxlen=10), Average: 12
@deque([9, 10, 11, 12, 13, 14, 15, 16, 17, 18], maxlen=10), Average: 13
@deque([10, 11, 12, 13, 14, 15, 16, 17, 18, 19], maxlen=10), Average: 14

Ben olsun TypeError: 'numpy.float64' object is not callableçağrı çalışırken averageyönteme
scls

Evet ... aslında
deque'in

17
Deque'in dahili olarak numpy dizileri kullanmadığını garanti ederim. collectionsstandart kitaplığın bir parçasıdır numpy, değildir. Üçüncü taraf kitaplıklara bağımlılıklar korkunç bir standart kitaplık oluşturur.

6

Burada zaten çok sayıda harika cevap olmasına rağmen, bahsedilen seçenekler için doğrudan bir zamanlama karşılaştırması bulamadım. Bu nedenle, lütfen aşağıda bir karşılaştırmada mütevazı girişimimi bulun.

Sınıf, yalnızca test amaçlı olarak, bir listtabanlı arabellek, bir collections.dequetabanlı arabellek ve bir Numpy.rolltabanlı arabellek arasında geçiş yapabilir .

updateYöntemin basit tutmak için her seferinde yalnızca bir değer eklediğini unutmayın .

import numpy
import timeit
import collections


class CircularBuffer(object):
    buffer_methods = ('list', 'deque', 'roll')

    def __init__(self, buffer_size, buffer_method):
        self.content = None
        self.size = buffer_size
        self.method = buffer_method

    def update(self, scalar):
        if self.method == self.buffer_methods[0]:
            # Use list
            try:
                self.content.append(scalar)
                self.content.pop(0)
            except AttributeError:
                self.content = [0.] * self.size
        elif self.method == self.buffer_methods[1]:
            # Use collections.deque
            try:
                self.content.append(scalar)
            except AttributeError:
                self.content = collections.deque([0.] * self.size,
                                                 maxlen=self.size)
        elif self.method == self.buffer_methods[2]:
            # Use Numpy.roll
            try:
                self.content = numpy.roll(self.content, -1)
                self.content[-1] = scalar
            except IndexError:
                self.content = numpy.zeros(self.size, dtype=float)

# Testing and Timing
circular_buffer_size = 100
circular_buffers = [CircularBuffer(buffer_size=circular_buffer_size,
                                   buffer_method=method)
                    for method in CircularBuffer.buffer_methods]
timeit_iterations = 1e4
timeit_setup = 'from __main__ import circular_buffers'
timeit_results = []
for i, cb in enumerate(circular_buffers):
    # We add a convenient number of convenient values (see equality test below)
    code = '[circular_buffers[{}].update(float(j)) for j in range({})]'.format(
        i, circular_buffer_size)
    # Testing
    eval(code)
    buffer_content = [item for item in cb.content]
    assert buffer_content == range(circular_buffer_size)
    # Timing
    timeit_results.append(
        timeit.timeit(code, setup=timeit_setup, number=int(timeit_iterations)))
    print '{}: total {:.2f}s ({:.2f}ms per iteration)'.format(
        cb.method, timeit_results[-1],
        timeit_results[-1] / timeit_iterations * 1e3)

Benim sistemimde bu:

list:  total 1.06s (0.11ms per iteration)
deque: total 0.87s (0.09ms per iteration)
roll:  total 6.27s (0.63ms per iteration)

4

Dolduğunda halka tampon örneğinin yeniden sınıflandırılması da dahil olmak üzere Python Yemek Kitabı'ndaki çözüme ne dersiniz ?

class RingBuffer:
    """ class that implements a not-yet-full buffer """
    def __init__(self,size_max):
        self.max = size_max
        self.data = []

    class __Full:
        """ class that implements a full buffer """
        def append(self, x):
            """ Append an element overwriting the oldest one. """
            self.data[self.cur] = x
            self.cur = (self.cur+1) % self.max
        def get(self):
            """ return list of elements in correct order """
            return self.data[self.cur:]+self.data[:self.cur]

    def append(self,x):
        """append an element at the end of the buffer"""
        self.data.append(x)
        if len(self.data) == self.max:
            self.cur = 0
            # Permanently change self's class from non-full to full
            self.__class__ = self.__Full

    def get(self):
        """ Return a list of elements from the oldest to the newest. """
        return self.data

# sample usage
if __name__=='__main__':
    x=RingBuffer(5)
    x.append(1); x.append(2); x.append(3); x.append(4)
    print(x.__class__, x.get())
    x.append(5)
    print(x.__class__, x.get())
    x.append(6)
    print(x.data, x.get())
    x.append(7); x.append(8); x.append(9); x.append(10)
    print(x.data, x.get())

Gerçekleştirmedeki dikkate değer tasarım seçimi, bu nesneler yaşam sürelerinin bir noktasında - tam olmayan arabellekten tam arabelleğe (ve bu noktada davranış değişikliklerine) - geri dönüşü olmayan bir durum geçişine maruz kaldığından, bunu değiştirerek modelledim self.__class__. Bu, her iki sınıfın da aynı yuvalara sahip olduğu sürece Python 2.2'de bile çalışır (örneğin, RingBuffer gibi iki klasik sınıf için ve __Fullbu tarifte iyi çalışır).

Bir örneğin sınıfını değiştirmek birçok dilde garip olabilir, ancak bu tarifte olduğu gibi davranışı büyük ölçüde etkileyen ara sıra, büyük, geri çevrilemez ve ayrı durum değişikliklerini temsil etmenin diğer yollarına Pythonic bir alternatiftir. Python'un her tür sınıf için desteklemesi iyi bir şey.

Kredi bilgileri: Sébastien Keim


Bu vs deque için bazı hız testleri yaptım. Bu, deque'den yaklaşık 7 kat daha yavaştır.
PolyMesh

@PolyMesh harika, yazara bildirmelisiniz!
d8aninja

1
bunun anlamı ne olabilir? Eski bir yayınlanmış belge. Yorumumun amacı, başkalarına bu cevabın güncel olmadığını bildirmek ve onun yerine deque kullanmaktır.
PolyMesh

@PolyMesh onu yayınladığında muhtemelen daha yavaştı; yazarla iletişim kurma talimatları kitabın giriş kısmındadır. Ben sadece bir olası alternatifi ilişkilendiriyorum. Ayrıca, "Keşke hız en iyi metrik olsaydı; ne yazık ki yalnızca iyi bir ölçü olabilir."
d8aninja

3

Bu oldukça eski Python tarifini de görebilirsiniz .

İşte NumPy dizisine sahip kendi versiyonum:

#!/usr/bin/env python

import numpy as np

class RingBuffer(object):
    def __init__(self, size_max, default_value=0.0, dtype=float):
        """initialization"""
        self.size_max = size_max

        self._data = np.empty(size_max, dtype=dtype)
        self._data.fill(default_value)

        self.size = 0

    def append(self, value):
        """append an element"""
        self._data = np.roll(self._data, 1)
        self._data[0] = value 

        self.size += 1

        if self.size == self.size_max:
            self.__class__  = RingBufferFull

    def get_all(self):
        """return a list of elements from the oldest to the newest"""
        return(self._data)

    def get_partial(self):
        return(self.get_all()[0:self.size])

    def __getitem__(self, key):
        """get element"""
        return(self._data[key])

    def __repr__(self):
        """return string representation"""
        s = self._data.__repr__()
        s = s + '\t' + str(self.size)
        s = s + '\t' + self.get_all()[::-1].__repr__()
        s = s + '\t' + self.get_partial()[::-1].__repr__()
        return(s)

class RingBufferFull(RingBuffer):
    def append(self, value):
        """append an element when buffer is full"""
        self._data = np.roll(self._data, 1)
        self._data[0] = value

4
Numpy kullanmak için +1, dairesel bir arabellek uygulamamak için -1. Bunu uygulama şeklinize göre, her tek bir öğe eklediğinizde tüm verileri değiştiriyorsunuz, bu O(n)zamana mal oluyor. Düzgün bir dairesel tampon uygulamak için , hem bir indeks hem de boyut değişkenine sahip olmalısınız ve veriler arabelleğin sonunu 'sararken' durumu doğru şekilde işlemeniz gerekir. Verileri alırken, arabelleğin başında ve sonunda iki bölümü birleştirmeniz gerekebilir.
Bas Swinckels

2

Bu herhangi bir kütüphane gerektirmez. Bir liste büyütür ve ardından indekse göre içinde döner.

Kapladığı alan çok küçüktür (kitaplık yok) ve en azından kuyruktan çıkarma işleminden iki kat daha hızlı çalışır. Bu gerçekten hareketli ortalamaları hesaplamak için iyidir, ancak öğelerin yukarıdaki gibi yaşa göre sıralanmadığını unutmayın.

class CircularBuffer(object):
    def __init__(self, size):
        """initialization"""
        self.index= 0
        self.size= size
        self._data = []

    def record(self, value):
        """append an element"""
        if len(self._data) == self.size:
            self._data[self.index]= value
        else:
            self._data.append(value)
        self.index= (self.index + 1) % self.size

    def __getitem__(self, key):
        """get element by index like a regular array"""
        return(self._data[key])

    def __repr__(self):
        """return string representation"""
        return self._data.__repr__() + ' (' + str(len(self._data))+' items)'

    def get_all(self):
        """return a list of all the elements"""
        return(self._data)

Ortalama değeri elde etmek için, örneğin:

q= CircularBuffer(1000000);
for i in range(40000):
    q.record(i);
print "capacity=", q.size
print "stored=", len(q.get_all())
print "average=", sum(q.get_all()) / len(q.get_all())

Sonuçlar:

capacity= 1000000
stored= 40000
average= 19999

real 0m0.024s
user 0m0.020s
sys  0m0.000s

Bu, dequeue ile eşdeğer sürenin yaklaşık 1 / 3'ü kadardır.


1
Senin __getitem__biraz daha güçlü olman gerekmez self._data[(key + self._index + 1) % self._size]mi?
Mateen Ulhaq

Neden +1 ile değiştirmek istersiniz? Şimdi, evet, fikir için aşağıdaki Basj varyantına bakın
MoonCactus

1

Seri programlama yapmadan önce bu sorunu yaşadım. Bir yıldan biraz daha uzun bir süre önce, verimli bir uygulama bulamadım, bu yüzden bir C uzantısı olarak bir tane yazdım ve ayrıca bir MIT lisansı altında pypi'de de mevcut . Süper basittir, yalnızca 8 bitlik işaretli karakterlerin tamponlarını işler, ancak esnek uzunluktadır, bu nedenle karakterlerden başka bir şeye ihtiyacınız varsa Struct veya üstüne bir şey kullanabilirsiniz. Şimdi bir google aramasında bugünlerde birkaç seçenek olduğunu görüyorum, bu yüzden bunlara da bakmak isteyebilirsiniz.


1

Cevabın doğru değil. Dairesel tampon ana iki prensibe sahiptir (https://en.wikipedia.org/wiki/Circular_buffer )

  1. Tamponun uzunluğu belirlenir;
  2. İlk giren ilk çıkar;
  3. Bir öğe eklediğinizde veya sildiğinizde, diğer öğeler konumlarını taşımamalıdır

aşağıdaki kodunuz:

def add_to_buffer( self, num ):
    self.mylist.pop( 0 )
    self.mylist.append( num )

Kodunuzu kullanarak listenin dolu olduğu bir durumu ele alalım:

self.mylist = [1, 2, 3, 4, 5]

şimdi 6 ekliyoruz, liste değiştirildi

self.mylist = [2, 3, 4, 5, 6]

Listede 1 olması beklenen öğeler konumlarını değiştirdi

kodunuz bir daire arabelleği değil, bir kuyruktur.

Basj'ın cevabı bence en etkili olanıdır.

Bu arada, bir daire tamponu, bir öğe ekleme işleminin performansını artırabilir.


1

Github'dan:

class CircularBuffer:

    def __init__(self, size):
        """Store buffer in given storage."""
        self.buffer = [None]*size
        self.low = 0
        self.high = 0
        self.size = size
        self.count = 0

    def isEmpty(self):
        """Determines if buffer is empty."""
        return self.count == 0

    def isFull(self):
        """Determines if buffer is full."""
        return self.count == self.size

    def __len__(self):
        """Returns number of elements in buffer."""
        return self.count

    def add(self, value):
        """Adds value to buffer, overwrite as needed."""
        if self.isFull():
            self.low = (self.low+1) % self.size
        else:
            self.count += 1
        self.buffer[self.high] = value
        self.high = (self.high + 1) % self.size

    def remove(self):
        """Removes oldest value from non-empty buffer."""
        if self.count == 0:
            raise Exception ("Circular Buffer is empty");
        value = self.buffer[self.low]
        self.low = (self.low + 1) % self.size
        self.count -= 1
        return value

    def __iter__(self):
        """Return elements in the circular buffer in order using iterator."""
        idx = self.low
        num = self.count
        while num > 0:
            yield self.buffer[idx]
            idx = (idx + 1) % self.size
            num -= 1

    def __repr__(self):
        """String representation of circular buffer."""
        if self.isEmpty():
            return 'cb:[]'

        return 'cb:[' + ','.join(map(str,self)) + ']'

https://github.com/heineman/python-data-structures/blob/master/2.%20Ubiquitous%20Lists/circBuffer.py


0

Asıl soru şuydu: " verimli " dairesel tampon. İstenen bu verimliliğe göre, aaronasterling'in cevabı kesinlikle doğru görünüyor. Python'da programlanmış özel bir sınıf kullanmak ve zaman işlemeyi collections.deque ile karşılaştırmak deque ile x5.2 kat hızlanma gösterir! İşte bunu test etmek için çok basit bir kod:

class cb:
    def __init__(self, size):
        self.b = [0]*size
        self.i = 0
        self.sz = size
    def append(self, v):
        self.b[self.i] = v
        self.i = (self.i + 1) % self.sz

b = cb(1000)
for i in range(10000):
    b.append(i)
# called 200 times, this lasts 1.097 second on my laptop

from collections import deque
b = deque( [], 1000 )
for i in range(10000):
    b.append(i)
# called 200 times, this lasts 0.211 second on my laptop

Bir diziyi bir listeye dönüştürmek için şunu kullanın:

my_list = [v for v in my_deque]

Daha sonra deque öğelerine O (1) rastgele erişim elde edeceksiniz. Elbette, bu yalnızca, bir kez ayarladıktan sonra deque'e birçok rastgele erişim yapmanız gerektiğinde değerlidir.


0

Bu, en son metin mesajlarını tutmayı amaçlayan bazı tamponlara aynı prensibi uygulamaktır.

import time
import datetime
import sys, getopt

class textbffr(object):
    def __init__(self, size_max):
        #initialization
        self.posn_max = size_max-1
        self._data = [""]*(size_max)
        self.posn = self.posn_max

    def append(self, value):
        #append an element
        if self.posn == self.posn_max:
            self.posn = 0
            self._data[self.posn] = value   
        else:
            self.posn += 1
            self._data[self.posn] = value

    def __getitem__(self, key):
        #return stored element
        if (key + self.posn+1) > self.posn_max:
            return(self._data[key - (self.posn_max-self.posn)])
        else:
            return(self._data[key + self.posn+1])


def print_bffr(bffr,bffer_max): 
    for ind in range(0,bffer_max):
        stored = bffr[ind]
        if stored != "":
            print(stored)
    print ( '\n' )

def make_time_text(time_value):
    return(str(time_value.month).zfill(2) + str(time_value.day).zfill(2)
      + str(time_value.hour).zfill(2) +  str(time_value.minute).zfill(2)
      + str(time_value.second).zfill(2))


def main(argv):
    #Set things up 
    starttime = datetime.datetime.now()
    log_max = 5
    status_max = 7
    log_bffr = textbffr(log_max)
    status_bffr = textbffr(status_max)
    scan_count = 1

    #Main Loop
    # every 10 secounds write a line with the time and the scan count.
    while True: 

        time_text = make_time_text(datetime.datetime.now())
        #create next messages and store in buffers
        status_bffr.append(str(scan_count).zfill(6) + " :  Status is just fine at : " + time_text)
        log_bffr.append(str(scan_count).zfill(6) + " : " + time_text + " : Logging Text ")

        #print whole buffers so far
        print_bffr(log_bffr,log_max)
        print_bffr(status_bffr,status_max)

        time.sleep(2)
        scan_count += 1 

if __name__ == '__main__':
    main(sys.argv[1:])  

0

Önceden tanımlanmış boyuttaki bir numpy dizisine göre bu dairesel tamponu kontrol edebilirsiniz . Buradaki fikir, bir arabellek oluşturmanız (numpy dizisi için bellek ayırmanız) ve daha sonra buna eklemenizdir. Veri girişi ve erişim çok hızlıdır. Bu modülü ihtiyaç duyduğunuz benzer bir amaç için oluşturdum. Benim durumumda, tamsayı veri üreten bir cihazım var. Verileri okudum ve gelecekteki analiz ve işleme için döngüsel tampona koydum.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.