Pyro4 Tutorial, Ошибка на разных машинах: недостаточно данных

Я начал использовать Pyro4 со вчерашнего дня, поэтому я экспериментирую с учебным кодом из официального документа. Все работало идеально локально, но я столкнулся с проблемами, когда я адаптировал эти примеры на разных машинах, в частности, на биржевом примере. Итак, вот мой адаптированный код на сервере и клиенте.
==== Серверная сторона ====
stockmarket.py

from __future__ import print_function
import random
import threading
import time
import Pyro4

class StockMarket(object):
    def __init__(self, marketname, symbols):
        self.name = marketname
        self.symbolmeans = {}
        for symbol in symbols:
            self.symbolmeans[symbol] = random.uniform(20, 200)
        self.aggregators = []

    def generate(self):
        quotes = {}
        for symbol, mean in self.symbolmeans.items():
            if random.random() < 0.2:
                quotes[symbol] = round(random.normalvariate(mean, 20), 2)
        print("new quotes generated for", self.name)
        for aggregator in self.aggregators:
            aggregator.quotes(self.name, quotes)

    def listener(self,aggregator):
        print("market {0} adding new aggregator".format(self.name))
        self.aggregators.append(aggregator)

    def symbols(self):
        return list(self.symbolmeans.keys())

    def run(self):
        def generate_symbols():
            while True:
                time.sleep(random.random())
                self.generate()
        thread = threading.Thread(target=generate_symbols)
        thread.setDaemon(True)
        thread.start()

def main():
    nasdaq = StockMarket("NASDAQ", ["AAPL", "CSCO", "MSFT", "GOOG"])
    newyork = StockMarket("NYSE", ["IBM", "HPQ", "BP"])

    daemon = Pyro4.Daemon("159.8.183.94")
    nasdaq_uri = daemon.register(nasdaq, "nasdaq")
    newyork_uri = daemon.register(newyork, "newyork")
    ns = Pyro4.locateNS()
    ns.register("example.stockmarket.nasdaq", nasdaq_uri)
    ns.register("example.stockmarket.newyork", newyork_uri)
    nasdaq.run()
    newyork.run()
    print("Stockmarkets running.")
    daemon.requestLoop()

if __name__ == "__main__":
    main()

aggregator.py

from __future__ import print_function
import Pyro4

class Aggregator(object):
    def __init__(self):
        self.viewers = {}
        self.symbols = []
    def add_symbols(self, symbols):
        self.symbols.extend(symbols)

    def available_symbols(self):
        return self.symbols

    def view(self, viewer, symbols):
        print("aggregator gets a new viewer, for symbols:", symbols)
        self.viewers[viewer] = symbols

    def quotes(self, market, stockquotes):
        print (market)
        print (stockquotes)
        for symbol, value in stockquotes.items():
            for viewer, symbols in self.viewers.items():
                if symbol in symbols:
                    viewer.quote(market, symbol, value)


def main():
    aggregator = Aggregator()
    daemon = Pyro4.Daemon(host="159.8.183.94")
    agg_uri = daemon.register(aggregator, "aggregator")
    ns = Pyro4.locateNS()
    ns.register("example.stockquote.aggregator", agg_uri)
    for market, market_uri in ns.list(prefix="example.stockmarket.").items():
        print("joining market", market)
        stockmarket = Pyro4.Proxy(market_uri)
        stockmarket.listener(aggregator)
        aggregator.add_symbols(stockmarket.symbols())
    if not aggregator.available_symbols():
        raise ValueError("no symbols found! (have you started the stock market first?)")
    print("Aggregator running. Symbols:", aggregator.available_symbols())
    daemon.requestLoop()

if __name__ == "__main__":
    main()

==== Клиентская сторона ====
viewer.py

from __future__ import print_function
import sys
import Pyro4

if sys.version_info < (3,0):
    input = raw_input


class Viewer(object):
    def quote(self, market, symbol, value):
        print("{0}.{1}: {2}".format(market, symbol, value))


def main():
    viewer = Viewer()
    daemon = Pyro4.Daemon()
    daemon.register(viewer)
    ns = Pyro4.locateNS(host="159.8.183.94", port=8080)
    aggregator_uri = ns.lookup("example.stockquote.aggregator")
    print ("aggregator uri is ", aggregator_uri)
    aggregator = Pyro4.Proxy(aggregator_uri)
    print("Available stock symbols:", aggregator.available_symbols())
    symbols = input("Enter symbols you want to view (comma separated):")
    symbols = [symbol.strip() for symbol in symbols.split(",")]
    aggregator.view(viewer, symbols)
    print("Viewer listening on symbols", symbols)
    daemon.requestLoop()

if __name__ == "__main__":
    main()

==== Как я запускаю код ====
На сервере я запустил следующий код, чтобы определить имя сервера

python -m Pyro4.naming --host 159.8.183.94 --port 8080

Затем я запустил stockmarket.py и aggregator.py, пока все в порядке. После этого я запустил viewer.py, набрал символы, которые хочу увидеть, и увидел ошибку из stockmarket.py.

Exception in thread Thread-18:
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.7/threading.py", line 763, in run
    self.__target(*self.__args, **self.__kwargs)
  File "stockmarket.py", line 37, in generate_symbols
    self.generate()
  File "stockmarket.py", line 24, in generate
    aggregator.quotes(self.name, quotes)
  File "/usr/local/lib/python2.7/dist-packages/Pyro4/core.py", line 171, in __call__
    return self.__send(self.__name, args, kwargs)
  File "/usr/local/lib/python2.7/dist-packages/Pyro4/core.py", line 410, in _pyroInvoke
    msg = message.Message.recv(self._pyroConnection, [message.MSG_RESULT], hmac_key=self._pyroHmacKey)
  File "/usr/local/lib/python2.7/dist-packages/Pyro4/message.py", line 168, in recv
    msg = cls.from_header(connection.recv(cls.header_size))
  File "/usr/local/lib/python2.7/dist-packages/Pyro4/socketutil.py", line 448, in recv
    return receiveData(self.sock, size)
  File "/usr/local/lib/python2.7/dist-packages/Pyro4/socketutil.py", line 182, in receiveData
    raise err
ConnectionClosedError: receiving: not enough data

Я думаю, что это всего лишь небольшая ошибка в моем коде, и я застрял здесь на несколько часов, любые предложения или помощь будут очень благодарны!! Спасибо!!

1 ответ

Отправленный код работает нормально, я запускаю его на своей машине без проблем. Конечно, я заменил ваш IP-адрес на имя хоста моей машины.

Так что это проблема настройки вашей сети или различия в конфигурации программного обеспечения на вашем сервере и клиентских компьютерах.

Чтобы исключить какие-либо проблемы с сетью, вы пытались запустить все это на одной машине (сервере)? Проблема только со зрителем (имеется в виду: после запуска только биржи и агрегатора, они печатают биржевые тикеры без ошибок?)

Кроме того, включите ведение журнала отладки и посмотрите, сможете ли вы найти что-нибудь полезное в журналах, которые создает Pyro. Может быть, это укажет вам на проблему. Посмотрите на http://pythonhosted.org/Pyro4/tipstricks.html

Наконец - вам действительно нужно предоставить больше информации, чтобы можно было даже понять, в чем может быть проблема. Какую ОС вы используете на сервере и клиенте? Какие версии Python и Pyro на сервере и клиенте? и т.п.

Другие вопросы по тегам