Ошибка скрученного плагина

Мы создали очень простое приложение, которое запускает TCP-протокол и выводит то, что вы вводите в STDIN.

Теперь я пытаюсь создать плагин twistd, чтобы иметь возможность запускать мое приложение следующим образом: echo start или либо twistd -n echo

При запуске twistd -n echo все работает как положено, при использовании команды echo start получаю ошибку: /home/vagrant/.env/bld/bin/echo: Unknown command: echo

Вот мой код:

echo/plugins.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from twisted.application import internet
from twisted.internet import endpoints
from twisted.internet.protocol import Factory
from twisted.python import usage

from echo.protocol import EchoProtocol


class Options(usage.Options):
    optParameters = [['port', 'p', 1234, 'Service port.']]


def makeService(options):
    from twisted.internet import reactor

    f = Factory()
    f.protocol = EchoProtocol

    ep = endpoints.TCP4ServerEndpoint(reactor, int(options['port']))
    return internet.StreamServerEndpointService(ep, f)

echo/protocol.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from twisted.internet.protocol import Protocol


class EchoProtocol(Protocol):
    def dataReceived(self, data):
        self.transport.write('You entered: {data}'.format(data=data))

echo/tap.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys

from twisted.python import usage
from twisted.scripts import twistd


class Start(twistd.ServerOptions):
    def parseOptions(self, args):
        sys.argv[1:] = self.getArguments(args)
        print('Starting echo service...')
        twistd.run()

    def getArguments(self, args):
        args.extend(['--pidfile', self.parent.pid])
        args.extend(['_bld_echo'])
        return args


class Options(usage.Options):
    pid = '/tmp/echo.pid'
    subCommands = [['start', None, Start, 'Launch echo service.']]


def main(argv=None):
    o = Options()
    try:
        o.parseOptions(argv)
    except usage.UsageError, e:
        raise SystemExit(str(e))

скрученный/плагины/echo_plugin.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from twisted.application.service import ServiceMaker

Finger = ServiceMaker(
    'EchoServiceMaker',  # name
    'echo.plugins',  # module
    'Description blah-blah.',  # description
    '_plgn_echo')  # tapname

setup.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from setuptools import find_packages
from setuptools import setup

setup(
    name='Echo',
    version='0.0.1',
    packages=find_packages(),
    entry_points={
        'console_scripts': [
            '_ep_echo=echo.tap:main',
        ],
    },
    install_requires=[
        'Twisted==16.0.0',
    ],
    include_package_data=True,
    zip_safe=False,)

Вот моя настройка virtualenv:

(bld)vagrant@/code/echo $ pip list
Echo (0.0.1)
pip (1.4.1)
setuptools (20.3.1)
Twisted (16.0.0)
wsgiref (0.1.2)
zope.interface (4.1.3)

Я поставил перед своими командами префиксы _ep_ и _bld_, потому что не был уверен, какая из них вызывается при вызове программы через twistd или при прямом вызове entry_point, но я пробовал любые возможная комбинация без успеха...

Когда я запускаю _ep_echo start, я получаю:

[twistd -help output...]

twistd reads a twisted.application.service.Application out of a file and runs
it.
Commands:
    conch            A Conch SSH service.
    dns              A domain name server.
    ftp              An FTP server.
    inetd            An inetd(8) replacement.
    mail             An email service
    manhole          An interactive remote debugger service accessible via
                     telnet and ssh and providing syntax coloring and basic line
                     editing functionality.
    manhole-old      An interactive remote debugger service.
    news             A news server.
    portforward      A simple port-forwarder.
    procmon          A process watchdog / supervisor
    socks            A SOCKSv4 proxy service.
    telnet           A simple, telnet-based remote debugging service.
    web              A general-purpose web server which can serve from a
                     filesystem or application resource.
    words            A modern words server
    xmpp-router      An XMPP Router server

/home/vagrant/.env/bld/bin/_ep_echo: Unknown command: _bld_echo

То же самое произойдет, если я заменю _bld_echo на _ep_echo.

Одна вещь кажется странной при просмотре вывода: в Twistd не зарегистрирована подкоманда echo.

Если я запускаю twistd --help, я получаю:

twistd reads a twisted.application.service.Application out of a file and runs
it.
Commands:
    _plgn_echo       Description blah-blah.
    conch            A Conch SSH service.
    dns              A domain name server.
    ftp              An FTP server.
    inetd            An inetd(8) replacement.
    mail             An email service
    manhole          An interactive remote debugger service accessible via
                     telnet and ssh and providing syntax coloring and basic line
                     editing functionality.
    manhole-old      An interactive remote debugger service.
    news             A news server.
    portforward      A simple port-forwarder.
    procmon          A process watchdog / supervisor
    socks            A SOCKSv4 proxy service.
    telnet           A simple, telnet-based remote debugging service.
    web              A general-purpose web server which can serve from a
                     filesystem or application resource.
    words            A modern words server
    xmpp-router      An XMPP Router server

И там вы можете увидеть зарегистрированную команду echo.

Это сводит меня с ума, есть идеи, в чем здесь проблема??

Обратите внимание, что я запускаю python setup.py install, а не python setup.py develop, последняя команда работает, но я не хочу запускать ее в рабочей среде


ИЗМЕНИТЬ

Хорошо, после поиска, почему сработало axiomatic start, а не мое echo start, я выяснил причину, удалив весь ненужный код из установки, и вот что я нашел (я не утверждаю, что это решение, я хотел бы услышать ответ @glyph по этому поводу )

Основное различие между Axiom и Echo заключается в этой строке в setup.py:

packages=find_packages() + ['twisted.plugins']

У меня не было дополнения + ['twisted.plugins'] к packages line, и теперь оно работает, но все еще возникает эта ошибка:

Unexpected error while writing cache file
Traceback (most recent call last):
  File "/home/vagrant/.env/bld/lib/python2.7/site-packages/Twisted-16.0.0-py2.7-linux-x86_64.egg/twisted/application/app.py", line 579, in parseOptions
    usage.Options.parseOptions(self, options)
  File "/home/vagrant/.env/bld/lib/python2.7/site-packages/Twisted-16.0.0-py2.7-linux-x86_64.egg/twisted/python/usage.py", line 262, in parseOptions
    for (cmd, short, parser, doc) in self.subCommands:
  File "/home/vagrant/.env/bld/lib/python2.7/site-packages/Twisted-16.0.0-py2.7-linux-x86_64.egg/twisted/application/app.py", line 596, in subCommands
    for plug in sorted(plugins, key=attrgetter('tapname')):
  File "/home/vagrant/.env/bld/lib/python2.7/site-packages/Twisted-16.0.0-py2.7-linux-x86_64.egg/twisted/plugin.py", line 213, in getPlugins
    allDropins = getCache(package)
--- <exception caught here> ---
  File "/home/vagrant/.env/bld/lib/python2.7/site-packages/Twisted-16.0.0-py2.7-linux-x86_64.egg/twisted/plugin.py", line 185, in getCache
    dropinPath.setContent(pickle.dumps(dropinDotCache))
exceptions.AttributeError: 'ZipPath' object has no attribute 'setContent'

Плагин работает, но мне бы очень хотелось узнать, почему мой первоначальный способ его установки не сработал...


person kitensei    schedule 21.03.2016    source источник
comment
Надеюсь, echo/plugins/py на самом деле относится к echo/plugins.py? Я собираюсь отредактировать вопрос, чтобы отразить это. (Если нет: это ваша проблема. :))   -  person Glyph    schedule 24.03.2016


Ответы (1)


Спасибо за чрезвычайно подробное объяснение вашей проблемы; Я смог точно воспроизвести его с помощью лишь одной незначительной настройки (создав __init__.py внутри echo/, чтобы сделать его правильным пакетом).

Во-первых, вот исправление:

diff --git a/echo/tap.py b/echo/tap.py
index d23571f..8e1ea84 100644
--- a/echo/tap.py
+++ b/echo/tap.py
@@ -15,7 +15,7 @@ class Start(twistd.ServerOptions):

     def getArguments(self, args):
         args.extend(['--pidfile', self.parent.pid])
-        args.extend(['_bld_echo'])
+        args.extend(['_plgn_echo'])
         return args

Причина, по которой это работает, заключается в том, что при написании такой команды вы обертываете выполнение подключаемого модуля Twisted, что означает то, что происходит в вашей синтетической командной строке, созданной args.extend — это tapname плагина Twisted, то же самое, что и в командной строке twistd.

Надеюсь, понятно, почему это _plgn_echo.

Я также должен похвалить вас за добавление этих префиксов, чтобы попытаться четко понять, какое имя, в частности, упоминается в каждой области кода. Предполагая, что этот ответ имеет для вас смысл, у вас будет гораздо лучшее понимание кода здесь, чем если бы вы просто вставили echo везде, даже если сначала это сработало :-).

person Glyph    schedule 24.03.2016
comment
Я полностью понимаю, но у меня все еще та же ошибка... /home/vagrant/.env/bld/bin/_ep_echo: Unknown command: _plgn_echo, я попытался зарегистрировать список argv и вот он: ['/home/vagrant/.env/bld/bin/_ep_echo', '--pidfile', '/tmp/echo.pid', '_plgn_echo']. Команда справки twistd по-прежнему не отображает команду _*_echo, которую я написал. - person kitensei; 29.03.2016
comment
Хорошо, я нашел, что не удалось, пожалуйста, посмотрите мои правки и спасибо за вашу поддержку :) - person kitensei; 29.03.2016