2010-12-08 2 views
18

나는 두 개의 '네트워크 소스'에서 동시에 읽는 프로그램을 가지고 있습니다. 스레딩을 사용하는 대신 비동기 방식을 시도했습니다.어떤 Python 비동기 라이브러리가 내 코드에 가장 적합합니까? 비동기? 꼬인?

import sniffer 

def first(): 
    for station in sniffer.sniff_wifi(): 
     log(station.mac()) 

def second(): 
    for station in sniffer.sniff_ethernet(): 
     log(station.mac()) 

first() 
second() 

는 두 sniffer 방법을 찾습니다이

내가 가지 내 프로그램이 수행 될 것을 보여줍니다 몇 가지 간단한 예제 코드와 함께 왔어요 ... 사용할 라이브러리 궁금해 나를 이끌었다 다소 좋아요 :

def sniff_wifi(self): 

    while True: 
     yield mac_address 

while True 루프가 분명히 차단됩니다.

asyncore을 표준 라이브러리의 일부로 사용하고자합니다. 타사 의존성은 보너스가 아닙니다. 그러나 내가 추천하는 경우 사용하지 않겠다는 의미는 아닙니다 ...

asyncore로 무엇을하려고합니까? 그렇다면 예제 코드를 'asyncore 코드'로 변환하는 방법을 보여 주시겠습니까? 좋은 asyncore 튜토리얼을 알고 있습니까?

답변

3

Asyncore는 훌륭하지만 기능이 풍부하지는 않지만 나중에 앱이 커질 때 문제가 발생할 수 있습니다. 즉, 프로토 타입을 작성하는 것이 좋습니다. 이 방법은 매우 간단합니다. 클래스의 특정 이벤트를 처리하는 메소드 (읽기가 가능할 때, 쓰기가 가능할 때 등)를 정의한 다음 asyncore.dispatcher (생각) 클래스에서 그 클래스를 서브 클래스 화하십시오.

official docs for the module과 Doug Hellmann의 우수한 PyMOTW article on it은 문서와 예제를 확인하기에 좋은 자료입니다.

프로토콜이 대화식 (예 : 이것을 보내고 받음)이면 표준 라이브러리와 함께 배포 된 아이디어 관리 모듈을 체크 아웃 할 수 있습니다.

트위스트는 훨씬 더 중한 방법입니다. 얼마나 큰 프로젝트가 더 많이 사용되는지는 확실하지만, 처음 사용하는 경험이 없기 때문에 더 말할 필요가 없습니다.

+0

왜 -1일까요? ... –

+0

asyncore/asynchat는 소켓 처리에 직접 연결될 때만 유용합니다.내 코드에서,'스니퍼 (sniffer) '는 모든 소켓 항목을 처리하고 결과를 산출합니다. asyncore가 수행하기를 원하는 것은 내 첫 번째 및 두 번째 함수를 실행하고 '스니퍼'가 데이터를 반환 할 때 콜백을 발행 할 수있게하려는 것입니다. 어떻게하면 좋을까요? (나는 downvote하지 않았다, btw) – dave

+1

asyncore/asynchat는 당신에게'select' 함수 호출 (보통 모든 비동기적인 것들이 빌드되는) 인 객체 지향 래퍼를 제공합니다. 'select'는 asyncore/asynchat가하는 것과 마찬가지로 파일 디스크립터에서 작동합니다. 몇 분만 있으면 무언가를 얻을 수 있습니다. –

49

Twisted는 모든 가능한 방식으로 좋습니다. 이식성이 뛰어나고 기능이 풍부하며 간단하고 확장 성이 뛰어나며 유지 관리가 잘되고 문서화가 잘되며 맛있는 오믈렛을 만들 수 있습니다. Asyncore는 모든 의도와 목적으로 폐기되었습니다.

그것은 트위스트 (나는 짧은 예에서 http/dns/ssh/smtp/pop/imap/irc/xmpp/process-spawning/multi-threading 서버를 보여 수있는 방법?) 짧은 대답에 우수한있는 모든 방법을 설명하기 어렵다, 그래서 대신 내가 사람들이 Twisted에 관해 가지고있는 것 같은 가장 일반적인 오해 중 하나에 초점을 맞 춥니 다 : asyncore보다 사용하기가 다소 복잡하거나 어렵습니다.

먼저 asyncore 예제부터 살펴 보겠습니다. 편향된 프리젠 테이션을 피하기 위해, 나는 여전히 asyncore를 조금 좋아하는 다른 누군가의 예를 사용할 것이다. 다음은 단순한 비동기식 예제 인 taken from Richard Jones' weblog입니다 (간략하게 설명을 생략 함).

먼저, 여기에 서버 :

import asyncore, socket 

class Server(asyncore.dispatcher): 
    def __init__(self, host, port): 
     asyncore.dispatcher.__init__(self) 
     self.create_socket(socket.AF_INET, socket.SOCK_STREAM) 
     self.bind(('', port)) 
     self.listen(1) 

    def handle_accept(self): 
     socket, address = self.accept() 
     print 'Connection by', address 
     EchoHandler(socket) 

class EchoHandler(asyncore.dispatcher_with_send): 
    def handle_read(self): 
     self.out_buffer = self.recv(1024) 
     if not self.out_buffer: 
      self.close() 

s = Server('', 5007) 
asyncore.loop() 

여기에 클라이언트 :

import asyncore, socket 

class Client(asyncore.dispatcher_with_send): 
    def __init__(self, host, port, message): 
     asyncore.dispatcher.__init__(self) 
     self.create_socket(socket.AF_INET, socket.SOCK_STREAM) 
     self.connect((host, port)) 
     self.out_buffer = message 

    def handle_close(self): 
     self.close() 

    def handle_read(self): 
     print 'Received', self.recv(1024) 
     self.close() 

c = Client('', 5007, 'Hello, world') 
asyncore.loop() 

가이 코드가 제대로 처리하지 않는 몇 가지 모호한 경우가 있지만이를 설명하는 것은 지루 및 복잡하고 코드는 이미이 답변을 충분히 길게 만들었습니다.

다음은 Twisted와 기본적으로 동일한 코드입니다. 첫째, 서버 : 지금

from twisted.internet import reactor, protocol as p 

class Echo(p.Protocol): 
    def dataReceived(self, data): 
     self.transport.write(data) 

class EchoFactory(p.Factory): 
    def buildProtocol(self, addr): 
     print 'Connection by', addr 
     return Echo() 

reactor.listenTCP(5007, EchoFactory()) 
reactor.run() 

그리고, 클라이언트 :

내가 당신의 관심을 끌기 위해 싶은 몇 가지가 있습니다
from twisted.internet import reactor, protocol as p 

class EchoClient(p.Protocol): 
    def connectionMade(self): 
     self.transport.write(self.factory.data) 

    def dataReceived(self, data): 
     print 'Received:', data 
     self.transport.loseConnection() 

class EchoClientFactory(p.ClientFactory): 
    protocol = EchoClient 
    def __init__(self, data): 
     self.data = data 

reactor.connectTCP('localhost', 5007, EchoClientFactory('Hello, world')) 
reactor.run() 

. 무엇보다 Twisted 예제는 25 % 더 짧습니다. asyncore는 40 줄, Twisted는 30 줄. 프로토콜이 점점 더 복잡 해짐에 따라 Twisted가 제공 할 수있는 asyncore에 대한 지원 코드를 더 많이 작성해야하므로이 차이가 더 커질 것입니다.

두 번째로, Twisted는 완전한 추상화을 제공합니다. asyncore 예제를 사용하면 socket 모듈을 사용하여 실제 네트워킹을 수행해야합니다. asyncore는 멀티플렉싱만을 제공합니다. portable behavior on platforms such as Windows이 필요하면 문제가됩니다. 또한 asyncore는 다른 플랫폼에서 비동기 서브 프로세스 통신을 수행 할 수있는 기능이 완전히 부족하다는 것을 의미합니다. 임의의 파일 설명자를 Windows의 select() 호출에 넣을 수 없습니다.

셋째, Twisted 예는 중성체입니다. EchoEchoFactoryEchoClientEchoClientFactory은 TCP와 관련이 없습니다. 이 클래스들을 SSH, SSL, UNIX 소켓 또는 파이프를 통해 연결할 수있는 라이브러리로 만들려면 connectTCP/listenTCP 콜을 하단에서만 변경하십시오. 프로토콜 논리에서 TLS와 같은 것을 지원하는 것은 매우 까다 롭습니다. 예를 들어, TLS의 '쓰기'는 하위 수준에서 '읽기'를 트리거합니다. 따라서 이러한 우려를 해결하기 위해서는 이러한 우려를 분리해야합니다.

마지막으로 MAC 주소와 이더넷 프레임을 직접 처리 할 경우 Twisted는 IP 및 이더넷 수준 네트워킹을 처리하기위한 저수준 라이브러리 인 Twisted Pair을 포함합니다. Twisted에서 가장 적극적으로 유지 관리되는 부분은 아닙니다. 코드가 꽤 오래되었습니다. 그러나 제대로 작동해야하며 그렇지 않은 경우 심각하게 버그를 발견하고 (결국) 고칠 수 있음을 확인합니다. 필자가 알고있는 한, asyncore에 필적할만한 라이브러리는 없으며 그러한 코드 자체는 포함되어 있지 않습니다.

+5

이것은 뒤틀린 저자의 훌륭한 소개 일 것입니다. – pyfunc

+1

+1. 매우 상세하고 요점은 있지만 나는 당신에게서 아무것도 덜 기대하지 않았다. :) –

+0

물론, 내 대답은 더 이상 관련이 없습니다! – pyfunc

0

Curl은 모든 관점에서 비 차단으로 설계되었으며 비동기 I/O 중에 값 비싼 연산 인 select를 사용하지 않습니다. 낮은 수준에서 컬은 유사한 성능을 제공 할 수있는 프레임 워크가있을 수 있지만 컬링보다 성능이 우수한 프레임 워크가없는 날짜까지 최적의 가능한 솔루션을 사용합니다.

그렇다면 자신의 소켓을 작성하는 것은 어떻습니까? Python에서 매우 쉽게 사용할 수 있으며, 목표를 명확히하고 일을 알고 있으면 놀라운 성능을 제공 할 수 있습니다.