为什么 python 带有线程库的脚本吃掉 100% CPU?
Why python script with threading lib eats 100% CPU?
我有一些客户端脚本,连接套接字并等待数据。
在服务器端有带有 json 包装器的 ZeroMQ 库。
所以,实际上,它是一个 json 数据格式的套接字连接。它是来自 metatrader 的股市数据。
所以我每分钟等待一条数据线。因为我的时间表是 M1.
问题是为什么这个脚本吃100%cpu?
大部分时间它应该等待数据而不做任何事情。我认为脚本中可能存在一些错误。但是我还没有threding技能。
请告诉我应该在哪里寻找问题。
这是一个脚本:
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, 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.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()
有关详细信息,请参阅 。
我有一些客户端脚本,连接套接字并等待数据。 在服务器端有带有 json 包装器的 ZeroMQ 库。
所以,实际上,它是一个 json 数据格式的套接字连接。它是来自 metatrader 的股市数据。 所以我每分钟等待一条数据线。因为我的时间表是 M1.
问题是为什么这个脚本吃100%cpu?
大部分时间它应该等待数据而不做任何事情。我认为脚本中可能存在一些错误。但是我还没有threding技能。 请告诉我应该在哪里寻找问题。
这是一个脚本:
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, 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.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()
有关详细信息,请参阅