효율적인 순환 버퍼?


109

효율적인 순환 버퍼 를 만들고 싶습니다.파이썬에서 ( 에서 정수 값의 평균을 구하는 것을 목표로).

목록을 사용하여 값을 수집하는 효율적인 방법입니까?

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

무엇이 더 효율적일까요 (그리고 왜)?


pop (0)은 목록에서 O (n) 연산이므로 순환 버퍼를 구현하는 효율적인 방법이 아닙니다. pop (0)은 목록의 첫 번째 요소를 제거하고 모든 요소를 ​​왼쪽으로 이동해야합니다. 대신 maxlen 속성과 함께 collections.deque를 사용하십시오. deque에는 추가 및 팝에 대한 O (1) 작업이 있습니다.
Vlad Bezden

답변:


205

나는 arg collections.deque와 함께 사용할 것 입니다.maxlen

>>> 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)

조리법 에 대한 문서에서 deque이 당신이 원하는 유사하다가. 이것이 가장 효율적이라는 나의 주장은 전적으로 최고 수준의 코드를 작성하는 습관을 가진 믿을 수 없을 정도로 숙련 된 승무원에 의해 C로 구현되었다는 사실에 있습니다.


7
+1 네, 좋은 배터리가 포함되어 있습니다. 순환 버퍼에 대한 작업은 O (1)이며 추가 오버 헤드는 C에 있으므로 여전히 매우 빠릅니다
John La Rooy

7
문서 maxlen가 정의 될 때 O (1) 임의 액세스를 보장하지 않기 때문에이 솔루션이 마음에 들지 않습니다 . O (n)은 deque무한대로 커질 수 있을 때 이해할 수 있지만 maxlen주어진 경우 요소 인덱싱은 일정한 시간이어야합니다.
lvella

1
내 생각 엔 배열이 아닌 연결된 목록으로 구현된다는 것입니다.
e-satis

1
아래답변 의 타이밍 이 정확 하다면 맞은 것 같습니다 .
djvg

13

목록의 헤드에서 팝하면 전체 목록이 복사되므로 비효율적입니다.

대신 고정 된 크기의 목록 / 배열과 항목을 추가 / 제거 할 때 버퍼를 통해 이동하는 인덱스를 사용해야합니다.


4
동의하다. 아무리 우아하거나 우아하지 않거나 어떤 언어를 사용하더라도 상관 없습니다. 실제로, 가비지 수집기 (또는 힙 관리자 또는 페이징 / 매핑 메커니즘 또는 실제 메모리 마법을 수행하는 모든 것)에 신경을 덜 쓸수록 좋습니다.

@RocketSurgeon 마법이 아니라 첫 번째 요소가 삭제 된 배열 일뿐입니다. 따라서 크기가 n 인 배열의 경우 이는 n-1 복사 작업을 의미합니다. 여기에는 가비지 수집기 또는 유사한 장치가 포함되지 않습니다.
기독교

3
나는 동의한다. 그렇게하는 것도 일부 사람들이 생각하는 것보다 훨씬 쉽습니다. 계속 증가하는 카운터를 사용하고 항목에 액세스 할 때 모듈로 연산자 (% arraylen)를 사용하십시오.
Andre Blum

IDEM, 당신은 내가 어떻게했는지 즉, 위의 내 게시물을 확인 할 수 있습니다
MoonCactus을

10

MoonCactus의 답변을 바탕으로 여기에 circularlist수업이 있습니다. 그의 버전과 다른 점은 여기에서 c[0]항상 가장 오래된 요소, c[-1]최근에 추가 된 요소, c[-2]두 번째 요소를 제공 한다는 것입니다. 이것은 응용 프로그램에 더 자연 스럽습니다.

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

수업:

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)'

[편집 됨] :data 기존 목록에서 초기화를 허용하는 선택적 매개 변수 추가 , 예 :

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)

좋은 추가. 파이썬 목록은 이미 음수 인덱스를 허용하지만 (-1), 예를 들어 목록에 "마지막"추가가 목록 에서 끝나기 때문에 순환 버퍼가 가득 차면 예상 값을 반환하지 않습니다 .
MoonCactus

1
@MoonCactus에서 작동합니다. 답변 위에 제가 준 6 가지 예를 참조하세요. 마지막 항목에서는 c[-1]항상 올바른 요소임을 알 수 있습니다 . __getitem__옳다.
Basj

오 그래, 내 말은 너의 것이 아니라 실패를 의미한다 . 미안하다. -오, 할 수 없습니다. 댓글이 너무 오래되었습니다.
MoonCactus

좋은 간단한 해결책. 기존 데이터에서 목록을 초기화 할 수있는 선택적 인수를 추가했습니다.
Orwellophile 19

9

Python의 deque는 느립니다. 대신 numpy.roll을 사용할 수도 있습니다. (n,) 또는 (n, 1)의 숫자 배열에서 숫자 어떻게 회전합니까?

이 벤치 마크에서 deque는 448ms입니다. Numpy.roll은 29ms입니다. http://scimusing.wordpress.com/2013/10/25/ring-buffers-in-pythonnumpy/


1
그러나 numpy.roll배열의 복사본을 반환합니다.
djvg

3
이 대답은 매우 오해의 소지가 있습니다. Python의 deque는 매우 빠르지 만 numpy 배열로 변환하면 연결하는 벤치 마크에서 상당히 느려집니다.
xitrium

7

deque 클래스를 사용하면 좋지만 질문 (평균)의 재 쿼리에 대해서는 이것이 내 해결책입니다.

>>> 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

내가 얻을 TypeError: 'numpy.float64' object is not callable호출하려고 할 때 average방법
scls

예 ... 사실 deque는 내부적으로 numpy 배열을 사용한다고 생각합니다 (@property를 제거한 후 잘 작동합니다)
scls

17
deque가 내부적으로 numpy 배열을 사용하지 않는다는 것을 보증합니다. collections표준 라이브러리의 일부입니다 numpy. 타사 라이브러리에 대한 종속성은 끔찍한 표준 라이브러리를 만듭니다.

6

여기에는 이미 많은 훌륭한 답변이 있지만 언급 된 옵션에 대한 타이밍의 직접적인 비교를 찾을 수 없습니다. 따라서 아래 비교에서 저의 겸손한 시도를 찾으십시오.

테스트 목적으로 만 클래스는 list기반 버퍼, collections.deque기반 버퍼 및 기반 버퍼 간에 전환 할 수 있습니다 Numpy.roll.

update메서드는 단순하게 유지하기 위해 한 번에 하나의 값만 추가합니다.

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)

내 시스템에서 이것은 다음을 산출합니다.

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

방법에 대한 파이썬 요리 책에서 솔루션 이 가득 차게 링 버퍼 인스턴스의 재 분류를 포함?

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())

구현에서 주목할만한 디자인 선택은 이러한 객체가 수명의 어느 시점에서 비가 역적 상태 전환을 겪기 때문입니다. 즉, 전체 버퍼가 아닌 버퍼에서 전체 버퍼로 (그리고 그 시점에서 동작이 변경됨) self.__class__. 이것은 두 클래스가 동일한 슬롯을 가지고있는 한 Python 2.2에서도 작동합니다 (예를 들어, RingBuffer 및 __Full이 레시피 와 같은 두 개의 클래식 클래스에서 잘 작동합니다 ).

인스턴스의 클래스를 변경하는 것은 많은 언어에서 이상 할 수 있지만,이 레시피에서와 같이 동작에 막대한 영향을 미치는 경우에 따라 대규모, 비가 역적, 개별적인 상태 변경을 나타내는 다른 방법에 대한 Python의 대안입니다. 파이썬이 모든 종류의 클래스를 지원한다는 것은 좋은 점입니다.

크레딧 : Sébastien Keim


나는 이것과 deque의 속도 테스트를했다. 이것은 deque보다 약 7 배 느립니다.
PolyMesh 2019

@PolyMesh 굉장합니다. 저자에게 알려야합니다!
d8aninja 19

1
그 요점은 무엇입니까? 오래전에 출판 된 문서입니다. 내 의견의 요점은이 답변이 오래되었다는 것을 다른 사람들에게 알리고 대신 deque를 사용하는 것입니다.
PolyMesh 2011

@PolyMesh 그가 그것을 출판했을 때 그것은 아마도 여전히 더 느 렸을 것입니다; 저자에게 연락하는 방법은 책 소개에 있습니다. 나는 단지 하나의 가능한 대안을 언급하고 있습니다. 또한 "속도 만 가장 좋은 지표라면 아쉽게도 좋은 지표 일 수 있습니다."
d8aninja 19.11. 08

3

이 꽤 오래된 Python 레시피를 볼 수도 있습니다 .

NumPy 배열을 사용하는 내 버전은 다음과 같습니다.

#!/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를 사용하면 +1, 순환 버퍼를 구현하지 않으면 -1. 구현 방식에 따라 단일 요소를 추가 할 때마다 모든 데이터가 이동하므로 시간이 걸립니다 O(n). 적절한 순환 버퍼 를 구현하려면 인덱스와 크기 변수가 모두 있어야하며 데이터가 버퍼 끝을 '둘러싸는'경우를 올바르게 처리해야합니다. 데이터를 검색 할 때 버퍼의 시작과 끝에서 두 섹션을 연결해야 할 수 있습니다.
바스 Swinckels

2

이것은 라이브러리가 필요하지 않습니다. 목록을 늘린 다음 색인별로 순환합니다.

풋 프린트는 매우 작고 (라이브러리 없음), 최소한 대기열에서 빼는 것보다 두 배 빠르게 실행됩니다. 이것은 실제로 이동 평균을 계산하는 데 유용하지만 항목이 위와 같이 연령별로 정렬되지 않습니다.

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)

평균 값을 얻으려면 다음과 같이하십시오.

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())

결과 :

capacity= 1000000
stored= 40000
average= 19999

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

이것은 대기열에서 빼는 것과 동등한 시간의 약 1/3입니다.


1
당신 __getitem__은 좀 더 강력 해야하지 self._data[(key + self._index + 1) % self._size]않습니까?
Mateen Ulhaq

+1 씩 이동하려는 이유는 무엇입니까? 자, 그렇다면, 아이디어를 아래 Basj 변형을 참조
MoonCactus

1

직렬 프로그래밍을하기 전에이 문제가 발생했습니다. 불과 1 년 전만해도 효율적인 구현을 찾을 수 없었기 때문에 결국 하나를 C 확장으로 작성 했으며 MIT 라이선스로 pypi에서도 사용할 수 있습니다 . 매우 기본적이며 8 비트 부호있는 문자의 버퍼 만 처리하지만 길이가 유연하므로 문자 이외의 것이 필요한 경우 Struct 또는 그 위에있는 것을 사용할 수 있습니다. 요즘에는 몇 가지 옵션이 있음을 Google 검색을 통해 알 수 있으므로 해당 옵션도 살펴보고 싶을 것입니다.


1

대답이 옳지 않습니다. 원형 버퍼 메인에는 두 가지 원칙이 있습니다 ( https://en.wikipedia.org/wiki/Circular_buffer )

  1. 버퍼의 길이가 설정됩니다.
  2. 선입 선출;
  3. 항목을 추가하거나 삭제할 때 다른 항목이 위치를 이동해서는 안됩니다.

아래 코드 :

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

코드를 사용하여 목록이 가득 찬 상황을 고려해 보겠습니다.

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

이제 6을 추가하면 목록이 다음과 같이 변경됩니다.

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

목록에서 1을 예상하는 항목이 위치를 변경했습니다.

코드는 원형 버퍼가 아니라 큐입니다.

Basj의 대답은 가장 효율적이라고 생각합니다.

그런데 원 버퍼는 항목을 추가하는 작업의 성능을 향상시킬 수 있습니다.


1

Github에서 :

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

원래 질문은 " 효율적인 "순환 버퍼였습니다. 요청한 효율성에 따르면 aaronasterling의 대답은 확실히 정확한 것 같습니다. Python으로 프로그래밍 된 전용 클래스를 사용하고 시간 처리를 collections.deque와 비교하면 deque를 사용한 x5.2 배 가속을 보여줍니다! 다음은이를 테스트하는 매우 간단한 코드입니다.

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

deque를 목록으로 변환하려면 다음을 사용하십시오.

my_list = [v for v in my_deque]

그러면 데크 항목에 대한 O (1) 무작위 액세스 권한이 부여됩니다. 물론 이것은 deque를 한 번 설정 한 후 여러 번 무작위로 액세스해야하는 경우에만 유용합니다.


0

이것은 가장 최근의 텍스트 메시지를 보관하기위한 일부 버퍼에 동일한 원칙을 적용합니다.

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

미리 정의 된 크기의 numpy 배열을 기반 으로이 순환 버퍼를 확인할 수 있습니다 . 아이디어는 버퍼를 만들고 (numpy 배열에 메모리 할당) 나중에 추가하는 것입니다. 데이터 삽입 및 검색이 매우 빠릅니다. 나는 당신이 필요로하는 비슷한 목적으로이 모듈을 만들었습니다. 제 경우에는 정수 데이터를 생성하는 장치가 있습니다. 데이터를 읽고 향후 분석 및 처리를 위해 원형 버퍼에 넣습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.