Почему мой код хорошо работает в Windows, но не в Ubuntu - PullRequest
0 голосов
/ 31 октября 2018

Этот код хорошо работает в Windows, но когда я перемещаю его в свой vps (ubuntu16.04, python3.6), возникает некоторая проблема.

import json
import time
import threading
import websocket
import requests
from datetime import datetime, timedelta, timezone

def run_in_thread(sec):
    def _wrapper(func):
        def __wrapper(self, *args, **kwargs):
            timer = threading.Timer(sec, func, [self, *args])
            timer.start()
            self._ws.on_open = self.on_open
            self._ws.run_forever()
            return self._result
        return __wrapper
    return _wrapper

class CybexHistoryAPI(object):
    def __init__(self, ws_endp):
        self._endpoint = ws_endp
        self.reset()

    def reset(self):
        self._ws = websocket.WebSocketApp(self._endpoint,
            on_message = self.on_message,
            on_error = self.on_error,
            on_close = self.on_close)
        self._login_api_id = -1
        self._history_api_id = -1
        self._api_is_ready = False
        self._call_id = 1

    def _send_msg(self, params):
        call = {"id": self._call_id, "method": "call",
                "params": params}
        self._ws.send(json.dumps(call))
        self._call_id += 1

    def on_open(self, ws):
        self._send_msg([1, "login", ["",""]])
        self._call_id = 1

    def on_error(self, ws, error):
        print('Remote node send an error [{}]'.format(error))

    def on_close(self, ws):
        print('Remote node closed our connection')

    def on_message(self, ws, msg):
        print(msg)
        if self._login_api_id < 0:
            result = json.loads(msg)
            self._login_api_id = result['id']
            self._send_msg([self._login_api_id, "history", []])
        elif self._history_api_id < 0:
            result = json.loads(msg)
            self._history_api_id = result['result']
            self._api_is_ready = True
        else:
            self._result = json.loads(msg)['result']
            self._ws.close()
            self.reset()

    @run_in_thread(0.01)
    def get_account_history(self, account_id, stop, limit, start):
        while not self._api_is_ready:
            time.sleep(0.01)
        self._send_msg([self._history_api_id, "get_account_history",
            [account_id, stop, limit, start]])

    @run_in_thread(0.01)
    def get_market_history(self, base_id, quote_id, ts, start, end):
        while not self._api_is_ready:
            time.sleep(0.01)
        self._send_msg([self._history_api_id, "get_market_history",
            [base_id, quote_id, ts, start, end]])

    @run_in_thread(0.01)
    def get_fill_order_history(self, base_id, quote_id, limit):
        while not self._api_is_ready:
            time.sleep(0.01)
        self._send_msg([self._history_api_id, "get_fill_order_history",
            [base_id, quote_id, limit]])

def scan_account(acc_id, max_len = 100):
    api = CybexHistoryAPI('wss://shanghai.51nebula.com')
    start = 0
    tot_len = 0
    while tot_len < max_len:
        print('start at 1.11.{}'.format(start))
        ret = api.get_account_history(acc_id, '1.11.1', 100, '1.11.' + str(start))
        if len(ret) == 0 or int(ret[0]['id'].split('.')[-1]) == start:
            break
        tot_len += len(ret)
        print('got {}'.format(len(ret)))
        print('end at {}'.format(ret[-1]['id']))
        #print(json.dumps(ret, indent=2))
        start = int(ret[-1]['id'].split('.')[-1]) - 1

    print(tot_len)
    return

def run_test():
    scan_account('1.2.38696')

if __name__ == '__main__':
    run_test()

Я получаю следующую ошибку:

Traceback (most recent call last):
File "ListenTransferRecord.py", line 197, in <module>
    run_test()
File "ListenTransferRecord.py", line 186, in run_test
    respone = scan_account(accountID,10)
File "ListenTransferRecord.py", line 147, in scan_account
    ret = api.get_account_history(acc_id, '1.11.1', 100, '1.11.' + str(start))
File "ListenTransferRecord.py", line 71, in __wrapper
    return self._result
AttributeError: 'CybexHistoryAPI' object has no attribute '_result'

Я не понимаю, почему он может хорошо работать в Windows, но не в Ubuntu.

И я попытался запустить простой код в моем VPS (Ubuntu), чтобы проверить, в порядке ли среда Python.

Я попытался переустановить все модули импорта этого кода. Но это все еще не работает.

1 Ответ

0 голосов
/ 31 октября 2018

Ошибка, которую вы получаете, просто вызывает ошибку, которая была уже там - self._result устанавливается только на определенное условие (в ветви else в методе on_message), но вы безусловный доступ к нему в вашем декораторе. По какой-то причине (которую мы не можем сказать, не имея гораздо более подробной информации - на самом деле, никто не может сказать, не протестировав код в вашей конкретной среде), вы никогда (до сих пор) не сталкивались с этим случаем при запуске кода в Window, но Сама ошибка не зависит от самой среды. Исправление здесь довольно простое: просто убедитесь, что для атрибута _result установлено всегда (в конечном итоге для некоторого значения часового типа, например None:

def on_message(self, ws, msg):
    print(msg)

    self._result = None # default value

    if self._login_api_id < 0:
        result = json.loads(msg)
        self._login_api_id = result['id']
        self._send_msg([self._login_api_id, "history", []])
    elif self._history_api_id < 0:
        result = json.loads(msg)
        self._history_api_id = result['result']
        self._api_is_ready = True
    else:
        self._result = json.loads(msg)['result']
        self._ws.close()
        self.reset()

Относительно того, почему у вас разное поведение в разных средах, это может быть вызвано множеством причин, по которым невозможно перечислить их все ... это может быть связано с задержкой в ​​сети и проблемами синхронизации между потоками, в зависимости от ОС детали реализации, фаза луны, что угодно, и, как я уже сказал, это, в основном, те проблемы, которые просто невозможно решить без прямого доступа к обеим вашим средам.

...