Django集成QuickFix执行多函数异常:文件无法访问
问题描述
运行下述集成QuickFix的Django代码时,程序仅执行命令并尝试打开传入文件,无法实现其他功能,同时提示文件不存在或无法打开。
import time import quickfix import quickfix44 from django.shortcuts import render from django.shortcuts import render import threading from django.http import JsonResponse from quickfix import Message, MsgType from django.views.decorators.csrf import csrf_exempt symbol=['EURUSD', 'NZDAUD'] messages=[] messages1=[] messages2=[] should_stop_data_flow = True def messageToString(message): ............ def securityListRequest(sessionID): ............... def marketDataRequest(sessionID): ............ class Application(quickfix.Application): def __init__(self): super().__init__() def onCreate(self, sessionID): print("onCreate:") self.session_id = sessionID target = sessionID.getTargetCompID().getString() sender = sessionID.getSenderCompID().getString() return def onLogon(self, sessionID): self.sessionID = sessionID print("onLogon:", f"Session ID: {self.sessionID}") message = marketDataRequest(sessionID) print("market data request:", messageToString(message)) quickfix.Session.sendToTarget(message, sessionID) def onLogout(self, sessionID): print("onLogout..") return def toAdmin(self, message, sessionID): print("toAdmin:", messageToString(message), '\n') return def toApp(self, message, sessionID): print("toApp:", messageToString(message), '\n') return def fromAdmin(self, message, sessionID): print("fromAdmin:", messageToString(message), '\n') return def fromApp(self, message, sessionID): msg = messageToString(message) print("fromApp:", msg, '\n') def keepAlive(self): while True: time.sleep(30) def run_fix(): global app settings = quickfix.SessionSettings("CCFIX.ini") app = Application() storeFactory = quickfix.FileStoreFactory(settings) logFactory = quickfix.FileLogFactory(settings) initiator = quickfix.SocketInitiator(app, storeFactory, settings, logFactory) initiator.start() app.keepAlive() def start_fix_thread(): fix_thread = threading.Thread(target=run_fix) fix_thread.start() def fix_example_view(request): global symbol start_fix_thread() return render(request, 'show_messages.html', {'messages': messages})
问题排查与修复方案
1. 配置文件路径问题
提示文件不存在,优先检查以下两点:
- 确保
CCFIX.ini文件放在Django项目根目录(与manage.py同目录),或者使用绝对路径指定文件位置,示例:settings = quickfix.SessionSettings("/opt/django_project/CCFIX.ini") - 确认文件权限,保证Django进程拥有读取该文件的权限。
2. 代码缩进错误
原代码中onLogout、toAdmin等方法未缩进在Application类内部,导致这些方法被识别为全局函数,QuickFix框架无法触发回调。修正后的缩进如上面代码示例所示。
3. 空实现函数补全
messageToString、marketDataRequest等函数仅保留占位符,必须补全实现才能正常工作:
- 示例
messageToString实现:def messageToString(message): msg_components = [] # 提取消息头 header = quickfix.FieldMap() message.getHeader().copyTo(header) msg_components.append(f"Header: {header}") # 提取消息体 body = quickfix.FieldMap() message.copyTo(body) msg_components.append(f"Body: {body}") # 提取消息尾 trailer = quickfix.FieldMap() message.getTrailer().copyTo(trailer) msg_components.append(f"Trailer: {trailer}") return "\n".join(msg_components) - 示例
marketDataRequest实现(符合QuickFix4.4规范):def marketDataRequest(sessionID): msg = quickfix44.MarketDataRequest() # 设置请求ID msg.setField(quickfix.MDReqID("MD-REQ-001")) # 设置订阅类型:快照+更新 msg.setField(quickfix.SubscriptionRequestType(quickfix.SubscriptionRequestType_SNAPSHOT_PLUS_UPDATES)) # 设置市场深度 msg.setField(quickfix.MarketDepth(0)) # 添加行情条目类型(买价+卖价) entry_group = quickfix44.MarketDataRequest.NoMDEntryTypes() entry_group.setField(quickfix.MDEntryType(quickfix.MDEntryType_BID)) msg.addGroup(entry_group) entry_group.setField(quickfix.MDEntryType(quickfix.MDEntryType_OFFER)) msg.addGroup(entry_group) # 添加目标交易对 symbol_group = quickfix44.MarketDataRequest.NoRelatedSym() symbol_group.setField(quickfix.Symbol("EURUSD")) msg.addGroup(symbol_group) symbol_group.setField(quickfix.Symbol("NZDAUD")) msg.addGroup(symbol_group) return msg
4. 消息存储与线程优化
fromApp方法未将收到的消息存入messages列表,无法在页面展示,补充代码:def fromApp(self, message, sessionID): msg = messageToString(message) print("fromApp:", msg, '\n') global messages messages.append(msg)keepAlive死循环会阻塞线程,添加退出条件并可选发送心跳包:def keepAlive(self): global should_stop_data_flow while not should_stop_data_flow: time.sleep(30) # 检查会话是否存活,发送心跳包 if quickfix.Session.lookupSession(self.sessionID): quickfix.Session.sendToTarget(quickfix.Message(), self.sessionID)
5. 避免重复启动线程
每次访问视图都会启动新的QuickFix线程,导致多会话冲突,添加启动判断:
fix_thread_running = False def start_fix_thread(): global fix_thread_running if not fix_thread_running: fix_thread = threading.Thread(target=run_fix) fix_thread.daemon = True # 设置为守护线程,随Django进程退出 fix_thread.start() fix_thread_running = True
内容的提问来源于stack exchange,提问作者mery
相关产品推荐
相关产品推荐

