diff --git a/__pycache__/config.cpython-312.pyc b/__pycache__/config.cpython-312.pyc new file mode 100644 index 0000000..072d452 Binary files /dev/null and b/__pycache__/config.cpython-312.pyc differ diff --git a/__pycache__/tools.cpython-312.pyc b/__pycache__/tools.cpython-312.pyc index 9b1bd47..119770c 100644 Binary files a/__pycache__/tools.cpython-312.pyc and b/__pycache__/tools.cpython-312.pyc differ diff --git a/asd.py b/asd.py deleted file mode 100644 index 8ea9f3a..0000000 --- a/asd.py +++ /dev/null @@ -1 +0,0 @@ -import requests \ No newline at end of file diff --git a/autobasic/__pycache__/dw_clienttrader.cpython-312.pyc b/autobasic/__pycache__/dw_clienttrader.cpython-312.pyc new file mode 100644 index 0000000..f057c11 Binary files /dev/null and b/autobasic/__pycache__/dw_clienttrader.cpython-312.pyc differ diff --git a/autobasic/dw_clienttrader.py b/autobasic/dw_clienttrader.py index 8929150..3bdc217 100644 --- a/autobasic/dw_clienttrader.py +++ b/autobasic/dw_clienttrader.py @@ -24,7 +24,7 @@ path = os.path.join(root_path,'broker_xiadan','东吴证券金融终端独立下 global engine engine = create_engine( 'mysql+pymysql://cn_ainvest_db:cn_ainvest_sd3a1@rm-2zewagytttzk6f24xno.mysql.rds.aliyuncs.com:3306/', - encoding="utf-8", echo=False) + echo=False) @@ -37,7 +37,13 @@ class DongWuClientTrader: self.path = exe_path self.account_name = account_name - self.log = Logger(f'{root_path}/logs',self.account_name) + + # 确保logs目录存在 + logs_dir = root_path / 'logs' + logs_dir.mkdir(exist_ok=True) + + # 初始化日志系统 + self._setup_logging() # 用户券商信息 sql = f"select * from ainvest_usercount where username='{account_name}'" @@ -46,6 +52,42 @@ class DongWuClientTrader: self.securities_password = str(df_count['securities_password'].tolist()[0]) self.communication_password = str(df_count['communication_password'].tolist()[0]) + def _setup_logging(self): + """设置日志系统""" + import logging + import os + + # 获取当前模块的logger + self.logger = logging.getLogger(__name__) + + # 为当前账户添加文件处理器,记录到logs目录 + logs_file = os.path.join(root_path, 'logs', f'{self.account_name}.log') + + # 检查是否已经有针对这个账户的处理器,避免重复添加 + account_handler_exists = False + for handler in self.logger.handlers: + if hasattr(handler, 'baseFilename') and handler.baseFilename == os.path.abspath(logs_file): + account_handler_exists = True + break + + if not account_handler_exists: + formatter = logging.Formatter('[%(asctime)s] [%(levelname)s] %(message)s', '%Y-%m-%d %H:%M:%S') + file_handler = logging.FileHandler(logs_file, encoding='utf-8') + file_handler.setFormatter(formatter) + file_handler.setLevel(logging.DEBUG) + self.logger.addHandler(file_handler) + + # 如果根logger没有处理器(单独运行时),添加控制台处理器 + root_logger = logging.getLogger() + if not root_logger.handlers: + console_handler = logging.StreamHandler() + console_handler.setFormatter(logging.Formatter('[%(asctime)s] [%(levelname)s] %(message)s', '%Y-%m-%d %H:%M:%S')) + console_handler.setLevel(logging.INFO) + self.logger.addHandler(console_handler) + + # 设置logger级别 + self.logger.setLevel(logging.DEBUG) + def exit(self): ''' 结束进程 @@ -74,12 +116,12 @@ class DongWuClientTrader: path=self.path, timeout=1 ) self.exit() - self.log.warn('There are running programs, and there are processes in retreat') + self.logger.warning('There are running programs, and there are processes in retreat') except Exception: pass #启动软件进程,输入账号密码 - self.log.info('Start login') + self.logger.info('Start login') start_time = time.time() # 重置mac @@ -96,12 +138,12 @@ class DongWuClientTrader: item = get_ip_data() #获取动态IP if item['ip'] in used_ip: get_ip_times += 1 - self.log.warn(f'代理IP重复,重新获取IP') + self.logger.warning(f'代理IP重复,重新获取IP') else: - self.log.info(f'代理IP已经获取{item}') + self.logger.info(f'代理IP已经获取{item}') break except Exception as e: - self.log.error(f'获取IP失败,请检查网络连接{e}') + self.logger.error(f'获取IP失败,请检查网络连接{e}') time.sleep(5) # raise ConnectionError(f"获取IP失败,请检查网络连接。错误详情: {e}") @@ -113,7 +155,7 @@ class DongWuClientTrader: # exit_ip = get_proxy_ip(proxy_ip,proxy_port) time_with_change_proxy = time.time()-start_time - self.log.info('全局代理设置成功') + self.logger.info('全局代理设置成功') insert_data= {'as_of_date':datetime.datetime.fromtimestamp(start_time).strftime('%Y-%m-%d %H:%M:%S.%f'), 'broker':broker, @@ -328,7 +370,7 @@ class DongWuClientTrader: one_text = self._app.window(control_id=0x0, class_name='#32770').window(control_id=0x410, class_name='Static').window_text() # 摘取合同信息 - self.log.info(one_text.replace('/n', ' ')) + self.logger.info(one_text.replace('/n', ' ')) time.sleep(0.2) # 确认申购委托 self._app.window(control_id=0x0, class_name="#32770", found_index=0).window(control_id=0x6, @@ -337,7 +379,7 @@ class DongWuClientTrader: # self._app.top_window().set_focus() one_text = self._app.window(control_id=0x0, class_name='#32770').window(control_id=0x3EC, class_name='Static').window_text() - self.log.info(one_text.replace('/n', ' ')) + self.logger.info(one_text.replace('/n', ' ')) time.sleep(0.2) self._app.window(control_id=0x0, class_name="#32770", found_index=0).window(control_id=0x2, class_name='Button').click() @@ -379,7 +421,7 @@ class DongWuClientTrader: #获取弹窗信息 result = self._app.top_window().window(control_id=0x3EC, class_name='Static').window_text() - self.log.info(result) + self.logger.info(result) pywinauto.keyboard.send_keys("{ENTER}") time.sleep(0.2) pywinauto.keyboard.send_keys("{ESC}") @@ -470,7 +512,7 @@ class DongWuClientTrader: self._copy_data() df_position = self._data_to_df() if len(df_position) == 0: - self.log.info('--------------------------------------无当日持仓--------------------------------------') + self.logger.info('--------------------------------------无当日持仓--------------------------------------') return pd.DataFrame() df_position['证券代码'] = df_position['证券代码'].apply(lambda x: tranTicker(str(x).replace('="', '').replace('"', ''))) df_position = df_position[['证券代码','证券名称','股票余额','可用余额','冻结数量','成本价','市价','市值','盈亏','盈亏比例(%)']] @@ -508,7 +550,7 @@ class DongWuClientTrader: self._copy_data() df = self._data_to_df() if len(df) == 0: - self.log.info('--------------------------------------无当日委托--------------------------------------') + self.logger.info('--------------------------------------无当日委托--------------------------------------') return pd.DataFrame() else: df = df[['委托时间', '证券代码', '证券名称', '操作', '委托价格', '委托数量', '成交数量', '成交均价', '股票成交金额']] @@ -544,7 +586,7 @@ class DongWuClientTrader: self._copy_data() df = self._data_to_df() if len(df) == 0: - self.log.info('--------------------------------------无当日成交--------------------------------------') + self.logger.info('--------------------------------------无当日成交--------------------------------------') return pd.DataFrame() else: df = df[['成交时间','证券代码','证券名称','操作','成交数量','成交均价']] @@ -603,8 +645,8 @@ class DongWuClientTrader: # one_text = self._app.top_window().window(control_id=0x410, class_name='Static').window_text() if '委托价格的小数部分应该为2位' in one_text: - # 点击“否” - self.log.warn(one_text.replace('/n',' ')) + # 点击"否" + self.logger.warning(one_text.replace('/n',' ')) self._app.top_window().window(control_id=0x7, class_name='Button').click() # 保留两位小数截断 price = str(price)[:-1] @@ -618,7 +660,7 @@ class DongWuClientTrader: one_text = self._app.top_window().window(control_id=0x410, class_name='Static').window_text() else: # 摘取合同信息 - self.log.info(one_text.replace('/n',' ')) + self.logger.info(one_text.replace('/n',' ')) time.sleep(0.2) # 确认买入 @@ -634,7 +676,7 @@ class DongWuClientTrader: class_name='Static').window_text() # self._app.top_window().set_focus() # one_text2 = self._app.top_window().window(control_id=0x3EC, class_name='Static').window_text() - self.log.info(one_text2.replace('/n', ' ')) + self.logger.info(one_text2.replace('/n', ' ')) time.sleep(0.5) # 确认合同 # self._app.top_window().set_focus() @@ -668,9 +710,9 @@ class DongWuClientTrader: try: self._app.top_window().set_focus() result_idcode = self._app.top_window().window(control_id=0x966, class_name='Static').window_text() - self.log.softInfo(result_idcode) + self.logger.info(result_idcode) if '验证码错误' in result_idcode: - self.log.warn('Verification code error') + self.logger.warning('Verification code error') self._app.top_window().window(control_id=0x2, class_name="Button").click() time.sleep(0.5) else: diff --git a/scheduler_init_proxy.py b/scheduler_init_proxy.py deleted file mode 100644 index bae44b2..0000000 --- a/scheduler_init_proxy.py +++ /dev/null @@ -1,107 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -""" -定时执行 init_proxy.py 脚本 -每整十分钟执行一次(00、10、20、30、40、50分) -""" - -import time -import datetime -import subprocess -import sys -import os -import logging -from pathlib import Path - -# 设置日志 -logging.basicConfig( - level=logging.INFO, - format='%(asctime)s - %(levelname)s - %(message)s', - handlers=[ - logging.FileHandler('scheduler_init_proxy.log', encoding='utf-8'), - logging.StreamHandler() - ] -) -logger = logging.getLogger(__name__) - -def execute_init_proxy(): - """执行 init_proxy.py 脚本""" - try: - script_path = Path(__file__).parent / "init_proxy.py" - if not script_path.exists(): - logger.error(f"脚本文件不存在: {script_path}") - return False - - # 使用当前 Python 解释器执行脚本 - 兼容老版本Python - result = subprocess.run( - [sys.executable, str(script_path)], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - universal_newlines=True - ) - - if result.returncode == 0: - logger.info("init_proxy.py 执行成功") - if result.stdout and result.stdout.strip(): - logger.info(f"输出: {result.stdout.strip()}") - else: - logger.error(f"init_proxy.py 执行失败,返回码: {result.returncode}") - if result.stderr and result.stderr.strip(): - logger.error(f"错误信息: {result.stderr.strip()}") - - return result.returncode == 0 - - except Exception as e: - logger.error(f"执行 init_proxy.py 时发生异常: {e}") - return False - -def wait_for_next_execution(): - """等待到下一个整十分钟""" - now = datetime.datetime.now() - current_minute = now.minute - - # 计算下一个整十分钟 - next_minute = ((current_minute // 10) + 1) * 10 - - # 处理小时进位 - if next_minute >= 60: - next_minute = 0 - next_execution = now.replace(minute=0, second=0, microsecond=0) + datetime.timedelta(hours=1) - else: - next_execution = now.replace(minute=next_minute, second=0, microsecond=0) - - wait_seconds = (next_execution - now).total_seconds() - logger.info(f"当前时间: {now.strftime('%Y-%m-%d %H:%M:%S')}") - logger.info(f"下次执行时间: {next_execution.strftime('%Y-%m-%d %H:%M:%S')}") - logger.info(f"等待 {wait_seconds:.0f} 秒") - - return wait_seconds - -def main(): - """主函数""" - logger.info("代理重置定时器启动") - logger.info("脚本将在每整十分钟执行一次 init_proxy.py") - - # 首次执行 - logger.info("执行首次代理重置...") - execute_init_proxy() - - # 定时循环 - while True: - try: - wait_seconds = wait_for_next_execution() - time.sleep(wait_seconds) - - logger.info("开始执行定时任务...") - execute_init_proxy() - - except KeyboardInterrupt: - logger.info("接收到中断信号,程序退出") - break - except Exception as e: - logger.error(f"定时器运行异常: {e}") - # 发生异常时等待60秒后继续 - time.sleep(60) - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/tools.py b/tools.py index 5ccb8a5..09011f0 100644 --- a/tools.py +++ b/tools.py @@ -633,46 +633,60 @@ class Logger(): """ def __init__(self, path, name, Flevel=logging.DEBUG): + import os + # 确保日志目录存在 + os.makedirs(path, exist_ok=True) + self.time = time.strftime("%Y-%m-%d") - self.fileName = path + '/' + name + ".log" - self.logger = logging.getLogger(self.fileName) + self.fileName = os.path.join(path, name + ".log") + + # 为每个实例创建唯一的logger名称,避免重复 + logger_name = f"{name}_{id(self)}" + self.logger = logging.getLogger(logger_name) self.logger.setLevel(Flevel) - if not self.logger.handlers: - fmt = logging.Formatter('[%(asctime)s] [%(levelname)s] %(message)s', '%Y-%m-%d %H:%M:%S') - fh = logging.FileHandler(self.fileName, encoding='utf-8') - fh.setFormatter(fmt) - fh.setLevel(Flevel) - self.logger.addHandler(fh) + + # 清除已有的处理器,避免重复 + self.logger.handlers.clear() + + # 设置格式 + fmt = logging.Formatter('[%(asctime)s] [%(levelname)s] %(message)s', '%Y-%m-%d %H:%M:%S') + + # 文件处理器 + fh = logging.FileHandler(self.fileName, encoding='utf-8') + fh.setFormatter(fmt) + fh.setLevel(Flevel) + self.logger.addHandler(fh) + + # 控制台处理器 + ch = logging.StreamHandler() + ch.setFormatter(fmt) + ch.setLevel(logging.INFO) + self.logger.addHandler(ch) - @output def debug(self, message): """ This is debug """ self.logger.debug(message) - @output def info(self, message): """ This is info """ self.logger.info(message) - @output def warn(self, message): """ This is warn """ - self.logger.warn(message) + self.logger.warning(message) - @output def error(self, message): """ This is error """ self.logger.error(message) - @output def critical(self, message): """ This is critical