问题描述
我有一些客户端脚本,该脚本在套接字上连接并等待数据。 在服务器端,有带有json包装器的ZeroMQ库。
因此,实际上,它是具有json数据格式的套接字连接。它是来自MetaTrader的股票市场数据。 所以我每分钟等待一条数据线。因为我的时间表是M1。
问题是为什么该脚本占用100%的CPU?
大多数情况下,它应该等待数据而不执行任何操作。我认为脚本中可能存在一些错误。但是我还没有技巧。 请告诉我我应该在哪里寻找问题。
这是一个脚本:
import zmq
import threading
class MTraderAPI:
def __init__(self,host=None):
self.HOST = host or 'localhost'
self.SYS_PORT = 15555 # REP/REQ port
self.DATA_PORT = 15556 # PUSH/PULL port
self.LIVE_PORT = 15557 # PUSH/PULL port
self.EVENTS_PORT = 15558 # PUSH/PULL port
# ZeroMQ timeout in seconds
sys_timeout = 1
data_timeout = 10
# initialise ZMQ context
context = zmq.Context()
# connect to server sockets
try:
self.sys_socket = context.socket(zmq.REQ)
# set port timeout
self.sys_socket.RCVTIMEO = sys_timeout * 1000
self.sys_socket.connect('tcp://{}:{}'.format(self.HOST,self.SYS_PORT))
self.data_socket = context.socket(zmq.PULL)
# set port timeout
self.data_socket.RCVTIMEO = data_timeout * 1000
self.data_socket.connect('tcp://{}:{}'.format(self.HOST,self.DATA_PORT))
except zmq.ZMQError:
raise zmq.ZMQBindError("Binding ports ERROR")
def _send_request(self,data: dict) -> None:
"""Send request to server via ZeroMQ System socket"""
try:
self.sys_socket.send_json(data)
msg = self.sys_socket.recv_string()
# terminal received the request
assert msg == 'OK','Something wrong on server side'
except AssertionError as err:
raise zmq.NotDone(err)
except zmq.ZMQError:
raise zmq.NotDone("Sending request ERROR")
def _pull_reply(self):
"""Get reply from server via Data socket with timeout"""
try:
msg = self.data_socket.recv_json()
except zmq.ZMQError:
raise zmq.NotDone('Data socket timeout ERROR')
return msg
def live_socket(self,context=None):
"""Connect to socket in a ZMQ context"""
try:
context = context or zmq.Context.instance()
socket = context.socket(zmq.PULL)
socket.connect('tcp://{}:{}'.format(self.HOST,self.LIVE_PORT))
except zmq.ZMQError:
raise zmq.ZMQBindError("Live port connection ERROR")
return socket
def streaming_socket(self,self.EVENTS_PORT))
except zmq.ZMQError:
raise zmq.ZMQBindError("Data port connection ERROR")
return socket
def construct_and_send(self,**kwargs) -> dict:
"""Construct a request dictionary from default and send it to server"""
# default dictionary
request = {
"action": None,"actionType": None,"symbol": None,"chartTF": None,"fromDate": None,"toDate": None,"id": None,"magic": None,"volume": None,"price": None,"stoploss": None,"takeprofit": None,"expiration": None,"deviation": None,"comment": None
}
# update dict values if exist
for key,value in kwargs.items():
if key in request:
request[key] = value
else:
raise KeyError('Unknown key in **kwargs ERROR')
# send dict to server
self._send_request(request)
# return server reply
return self._pull_reply()
api = MTraderAPI()
print(api.construct_and_send(action="CONFIG",symbol="XBRUSD.c",chartTF="TICK"))
def _t_livedata():
socket = api.live_socket()
while True:
try:
last_candle = socket.recv_json()
except zmq.ZMQError:
raise zmq.NotDone("Live data ERROR")
print(last_candle)
def _t_streaming_events():
socket = api.streaming_socket()
while True:
try:
trans = socket.recv_json()
request,reply = trans.values()
except zmq.ZMQError:
raise zmq.NotDone("Streaming data ERROR")
print(request)
print(reply)
t = threading.Thread(target=_t_livedata,daemon=True)
t.start()
t = threading.Thread(target=_t_streaming_events,daemon=True)
t.start()
while True:
pass
解决方法
它是你的:
while True:
pass
最后,的重点是消耗CPU。使用time.sleep
添加少量睡眠,CPU使用率将降低。或者,如果仅等待线程完成,只需加入它们,它将阻塞直到执行完成。
例如:
from time import sleep
while True:
sleep(0.1)
或者如果您将线程对象收集在列表中,则应该:
for t in threads:
t.join()
有关更多信息,请参考following post。