2010-02-17 2 views
0

Я создавал сокет асинхронного сервера, который отправляет и возвращает xml с помощью twisted.простой скрученный сервер (twistd .tap) с ошибкой экземпляра pexpect

Приложение отлично работает! а потому, что моя главная цель заключалась в встроить его в сценарии init.d и заставить ее работать в фоновом режиме, я решил превратить его в «скрученном приложении», чтобы запустить его с помощью twistd

# from twisted.internet import reactor 
from twisted.internet.protocol import ServerFactory 
from twisted.protocols.basic import LineOnlyReceiver 
from twisted.application import internet, service 

from xml.etree import ElementTree as ET 

from aMuleClass import amulecmd 

class DialogueProtocol(LineOnlyReceiver): 
    def connectionMade(self): 
     print "Connected: %s" % self.transport.getPeer().host 
def lineReceived(self, line): 
    parsed= ET.XML(line) 
    if parsed.attrib['type'] == 'request': 
     if parsed.attrib['prompt'] == 'results': 
      self.transport.write(self.factory.mule.results()) 
     elif parsed.attrib['prompt'] == 'downloads': 
      self.transport.write(self.factory.mule.downloads()) 
     else: 
      print "Invalid request: %s\n" % line 
    else: 
     query= parsed.attrib['value'] 
     if parsed.attrib['type'] == 'search': 
      print "must search for %s" % query 
      self.factory.mule.search(query) 
     elif parsed.attrib['type'] == 'cancel': 
      print "must cancel %s" % query 
      self.factory.mule.command("cancel %s" % query) 
     elif parsed.attrib['type'] == 'download': 
      print "must download %s" % query 
      self.factory.mule.command("download %s" % query) 

class DialogueProtocolFactory(ServerFactory): 
def __init__(self): 
    self.protocol= DialogueProtocol 
    self.mule= amulecmd() 

def main(): 
factory= DialogueProtocolFactory() 
port = 14000 
# 
daemon= internet.TCPServer(port, factory) 
application= service.Application("aMuleSocket") 
# 
daemon.setServiceParent(application) 

if __name__ == '__main__': 
main() 

Запуска этого с «twistd -noy file» (debug) работает ОТЛИЧНО. Проблема в том, когда я хочу создать свой сценарий! («twistd -y file»), ответчик сокета отвечает, и журнал заполняется ошибками от pexpect, который импортируется в моем классе amulecmd ... pexpect общается с приложением терминала-запроса и возвращает ответы на сокет.

файл_журнала:

2010/02/17 19:54 +0200 [-] Log opened. 
2010/02/17 19:54 +0200 [-] twistd 2.5.0 (/usr/bin/python 2.5.2) starting up 
2010/02/17 19:54 +0200 [-] reactor class: <class   'twisted.internet.selectreactor.SelectReactor'> 
2010/02/17 19:54 +0200 [-] Loading aMuleSocket.tac... 
2010/02/17 19:54 +0200 [-] Starting parent 
2010/02/17 19:54 +0200 [-] Loaded. 
2010/02/17 19:54 +0200 [-] __builtin__.DialogueProtocolFactory starting on 2000 
2010/02/17 19:54 +0200 [-] Starting factory <__builtin__.DialogueProtocolFactory instance at 0x82dbd8c> 
2010/02/17 19:54 +0200 [__builtin__.DialogueProtocolFactory] Connected: 192.168.0.2 
2010/02/17 19:54 +0200 [DialogueProtocol,0,192.168.0.2] Unhandled Error 
Traceback (most recent call last): 
File "/usr/lib/python2.5/site-packages/twisted/python/log.py", line 48, in  callWithLogger 
return callWithContext({"system": lp}, func, *args, **kw) 
File "/usr/lib/python2.5/site-packages/twisted/python/log.py", line 33, in callWithContext 
return context.call({ILogContext: newCtx}, func, *args, **kw) 
File "/usr/lib/python2.5/site-packages/twisted/python/context.py", line 59, in callWithContext 
return self.currentContext().callWithContext(ctx, func, *args, **kw) 
File "/usr/lib/python2.5/site-packages/twisted/python/context.py", line 37, in callWithContext 
return func(*args,**kw) 
--- <exception caught here> --- 
File "/usr/lib/python2.5/site-packages/twisted/internet/selectreactor.py", line 139, in _doReadOrWrite 
why = getattr(selectable, method)() 
File "/usr/lib/python2.5/site-packages/twisted/internet/tcp.py", line 362, in doRead 
return self.protocol.dataReceived(data) 
File "/usr/lib/python2.5/site-packages/twisted/protocols/basic.py", line 149, in dataReceived 
self.lineReceived(line) 
File "aMuleSocket.tac", line 19, in lineReceived 
self.transport.write(self.factory.mule.downloads()) 
File "/home/hecyra/amule_scripts/amule-remote-read-only/server/aMuleClass.py", line 60, in downloads 
list= self.command('show DL').splitlines() 
File "/home/hecyra/amule_scripts/amule-remote-read-only/server/aMuleClass.py", line 42, in command 
self.prompt() 
File "/home/hecyra/amule_scripts/amule-remote-read-only/server/aMuleClass.py", line 27, in prompt 
self.process.expect('aMulecmd') 
File "/usr/lib/python2.5/site-packages/pexpect.py", line 1064, in expect 
return self.expect_list(compiled_pattern_list, timeout, searchwindowsize) 
File "/usr/lib/python2.5/site-packages/pexpect.py", line 1116, in expect_list 
c = self.read_nonblocking (self.maxread, timeout) 
File "/usr/lib/python2.5/site-packages/pexpect.py", line 656, in read_nonblocking 
if not self.isalive(): 
File "/usr/lib/python2.5/site-packages/pexpect.py", line 914, in isalive 
raise ExceptionPexpect ('isalive() encountered condition where "terminated" is 0, but there was no child process. Did someone else call waitpid() on our process?') 
pexpect.ExceptionPexpect: isalive() encountered condition where "terminated" is 0,   but there was no child process. Did someone else call waitpid() on our process? 

что это может быть ?? все что мне нужно, чтобы фон этого сценария :(выглядел легко

ответ

3

Вы нерест дочернего процесса, прежде чем режим демона. После этого ребенка режим демона теперь ребенок INIT, а не ребенок вашего демона.

Вы необходимо создать подкласс from twisted.application.service import Service и породить дочерний процесс в startService, который будет называться после

режим демона

A La:. Twisted network client with multiprocessing workers?

Edit: реализация

я не могу проверить это полностью, как я не ваш amulecmd, но попробовать что-то больше, как это:

#!/usr/bin/env python 
# vim:ai:et:ts=2:sw=2:bg=dark 
from twisted.internet import protocol 
from twisted.protocols.basic import LineOnlyReceiver 
from twisted.application import service 


from xml.etree import ElementTree as ET 

from aMuleClass import amulecmd 

class DialogueProtocol(LineOnlyReceiver): 
    def connectionMade(self): 
    print "Connected: %s" % self.transport.getPeer().host 
    def lineReceived(self, line): 
    parsed= ET.XML(line) 
    if parsed.attrib['type'] == 'request': 
     if parsed.attrib['prompt'] == 'results': 
     self.transport.write(self.factory.mule.results()) 
     elif parsed.attrib['prompt'] == 'downloads': 
     self.transport.write(self.factory.mule.downloads()) 
     else: 
     print "Invalid request: %s\n" % line 
    else: 
     query= parsed.attrib['value'] 
     if parsed.attrib['type'] == 'search': 
     print "must search for %s" % query 
     self.factory.mule.search(query) 
     elif parsed.attrib['type'] == 'cancel': 
     print "must cancel %s" % query 
     self.factory.mule.command("cancel %s" % query) 
     elif parsed.attrib['type'] == 'download': 
     print "must download %s" % query 
     self.factory.mule.command("download %s" % query) 

class MyService(service.Service): 
    def __init__(self,port=14000): 
    self.port = port 
    def startService(self): 
    self.factory = protocol.Factory() 
    self.factory.protocol = DialogueProtocol 
    from twisted.internet import reactor 
    reactor.callWhenRunning(self.startListening) 
    def startListening(self): 
    self.factory.mule = amulecmd() 
    from twisted.internet import reactor 
    self.listener = reactor.listenTCP(self.port,self.factory) 
    print "Started listening" 
    def stopService(self): 
    self.listener.stopListening() 

if __name__ == '__main__': 
    pass 
else: 
    application = service.Application("aMuleSocket") 
    services = service.IServiceCollection(application) 
    MyService().setServiceParent(services) 
+0

Это здорово !! я действительно «рад», у кого-то была такая же проблема, как у меня, и ей удалось ее решить! Класс amulecmd должен быть порожден - это подкласс ServerFactory, так что он может быть доступен любому соединению, как я могу это сделать? я правильно реализовал MultiprocessingService, но если я создаю процесс там, я не знаю, как получить к нему доступ. идеи? Спасибо за помощь – PirosB3

+0

Если ваш 'amulecmd' возвращает объект с помощью метода, который позволяет изящно завершить подпроцесс, вы можете вызвать его в методе' stopService'. – MattH

+0

Еще раз спасибо ... Это прекрасно работает !!! : D – PirosB3

Смежные вопросы