Functions-d 1.34__tar.gz → 1.35__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,10 +9,6 @@ import urllib.request
9
9
  import WeComMsg
10
10
  import xlwings as xw
11
11
  import yagmail
12
- import smtplib
13
- from email.mime.multipart import MIMEMultipart
14
- from email.mime.text import MIMEText
15
- from email.mime.application import MIMEApplication
16
12
  import HiveClient
17
13
  from PIL import ImageGrab, Image
18
14
  from bs4 import BeautifulSoup
@@ -29,9 +25,12 @@ from tenacity import retry, stop_after_attempt, wait_fixed
29
25
  import requests
30
26
  import pandas as pd
31
27
  import os
32
- from io import BytesIO
33
- from requests.adapters import HTTPAdapter
34
- from urllib3.util.retry import Retry
28
+ import time
29
+ import smtplib
30
+ from email.mime.multipart import MIMEMultipart
31
+ from email.mime.text import MIMEText
32
+ from email.mime.application import MIMEApplication
33
+ from email.mime.image import MIMEImage
35
34
 
36
35
 
37
36
  class DataProcessingAndMessaging:
@@ -79,6 +78,15 @@ class DataProcessingAndMessaging:
79
78
  self.wechat_doc_access_token = None
80
79
  self._wechat_doc_logger = None # 企微文档独立日志器(延迟初始化)
81
80
 
81
+ # -------------------------- 邮件SMTP全局配置 --------------------------
82
+ self.SMTP_SENDER = "cc_yingxiao@xin.com"
83
+ self.SMTP_PWD = "cw46pfeznNQx"
84
+ self.SMTP_HOST = "mail.xin.com"
85
+ self.SMTP_PORT = 587
86
+ self.SMTP_TIMEOUT = 300 # 超时延长至5分钟
87
+ self.MAIL_RETRY_TIMES = 3 # 失败重试3次
88
+ self.MAIL_RETRY_INTERVAL = 5 # 重试间隔5秒
89
+
82
90
 
83
91
  # -------------------------- 企微文档日志:延迟初始化独立日志器 --------------------------
84
92
  def _init_wechat_doc_logger(self):
@@ -815,16 +823,14 @@ class DataProcessingAndMessaging:
815
823
  self.screen(filename, sheet_name,
816
824
  f"{start_range}:%s" % (self.column_label(len(data.columns)) + str(len(data) + 3)), image_path)
817
825
 
818
- # -------------------------- 发送邮件(新版-优化增强版) --------------------------
826
+ # -------------------------- 发送邮件(新版-优化增强版+重试+防超时) --------------------------
819
827
  def send_email_new(self, recipient_emails, cc_emails=None, bcc_emails=None, subject="", html_body="",
820
828
  attachments=None):
821
829
  # 1. 内部工具:格式化邮箱(和旧版完全对齐,转列表+过滤无效值)
822
830
  def format_email(emails):
823
831
  if not emails:
824
832
  return []
825
- # 单个邮箱转列表,列表直接使用
826
833
  email_list = [emails] if isinstance(emails, str) else emails
827
- # 过滤:非空字符串 + 简单格式校验(含@和.)
828
834
  valid_emails = [
829
835
  e.strip() for e in email_list
830
836
  if isinstance(e, str) and e.strip() and '@' in e.strip() and '.' in e.strip()
@@ -853,17 +859,16 @@ class DataProcessingAndMessaging:
853
859
  }
854
860
  return mime_map.get(suffix, 'application/octet-stream')
855
861
 
856
- # 3. 参数标准化处理(修复None报错隐患)
862
+ # 3. 参数标准化处理
857
863
  subject = subject.strip()
858
864
  to_emails = format_email(recipient_emails)
859
865
  cc_emails = format_email(cc_emails)
860
866
  bcc_emails = format_email(bcc_emails)
861
867
  attachments = attachments or []
862
- # 附件标准化:单个字符串转列表
863
868
  if isinstance(attachments, str):
864
869
  attachments = [attachments.strip()]
865
870
 
866
- # 4. 核心参数校验(提前报错,避免无效连接)
871
+ # 4. 核心参数校验
867
872
  if not to_emails:
868
873
  err_msg = "❌ 邮件发送失败:无有效收件人邮箱"
869
874
  self.logger.error(err_msg)
@@ -875,7 +880,7 @@ class DataProcessingAndMessaging:
875
880
  print(err_msg)
876
881
  raise ValueError(err_msg)
877
882
 
878
- # 5. 控制台打印(和旧版完全对齐,实时展示发送进度)
883
+ # 5. 控制台打印
879
884
  print(f"📧 开始发送邮件 - 主题: {subject}")
880
885
  print(f"📥 收件人: {', '.join(to_emails)}")
881
886
  if cc_emails:
@@ -886,7 +891,7 @@ class DataProcessingAndMessaging:
886
891
  attach_names = [os.path.basename(att) for att in attachments]
887
892
  print(f"📎 附件: {', '.join(attach_names)}")
888
893
 
889
- # 6. 日志记录(和原新版逻辑对齐)
894
+ # 6. 日志记录
890
895
  self.logger.info(f"开始发送邮件 - 主题: {subject}")
891
896
  self.logger.info(f"收件人: {', '.join(to_emails)}")
892
897
  if cc_emails:
@@ -897,106 +902,147 @@ class DataProcessingAndMessaging:
897
902
  attach_names = [os.path.basename(att) for att in attachments]
898
903
  self.logger.info(f"附件: {', '.join(attach_names)}")
899
904
 
900
- # 7. SMTP固定配置
901
- sender_email = 'cc_yingxiao@xin.com'
902
- sender_password = 'cw46pfeznNQx'
903
- smtp_host = 'mail.xin.com'
904
- smtp_port = 587
905
+ # 所有收件人提前合并去重
906
+ all_recipients = list(set(to_emails + cc_emails + bcc_emails))
907
+ last_exception = None
905
908
 
906
- try:
907
- # 8. 构建邮件对象
908
- msg = MIMEMultipart()
909
- msg['From'] = sender_email
910
- msg['To'] = ', '.join(to_emails)
911
- if cc_emails:
912
- msg['Cc'] = ', '.join(cc_emails)
913
- if bcc_emails:
914
- msg['Bcc'] = ', '.join(bcc_emails)
915
- msg['Subject'] = subject
916
-
917
- # 9. 邮件正文(修复中文乱码,指定utf-8编码)
918
- body = MIMEText(html_body, 'html', 'utf-8')
919
- msg.attach(body)
920
-
921
- # 10. 附件处理(全格式支持+提前校验)
922
- valid_attachments = []
923
- for attachment in attachments:
924
- attachment = attachment.strip()
925
- if not os.path.exists(attachment):
926
- error_msg = f"❌ 邮件发送失败:附件不存在 -> {attachment}"
927
- self.logger.error(error_msg)
928
- print(error_msg)
929
- raise FileNotFoundError(error_msg)
930
-
931
- # 自动识别MIME类型,适配不同文件
932
- file_name = os.path.basename(attachment)
933
- mime_type = get_mime_type(attachment)
934
-
935
- with open(attachment, 'rb') as file:
936
- file_content = file.read()
937
-
938
- # 按文件类型选择对应的MIME对象
939
- if mime_type.startswith('image/'):
940
- part = MIMEImage(file_content, _subtype=mime_type.split('/')[1])
941
- elif mime_type == 'text/plain' or mime_type == 'text/csv':
942
- part = MIMEText(file_content.decode('utf-8'), _subtype=mime_type.split('/')[1], _charset='utf-8')
943
- else:
944
- part = MIMEApplication(file_content, _subtype=mime_type.split('/')[1])
945
-
946
- part['Content-Disposition'] = f'attachment; filename="{file_name}"'
947
- part['Content-Type'] = f'{mime_type}; name="{file_name}"'
948
- msg.attach(part)
949
- valid_attachments.append(file_name)
950
- self.logger.debug(f"已添加附件: {file_name}")
951
- print(f"✅ 已添加附件: {file_name}")
952
-
953
- # 11. 连接SMTP服务器并发送(修复核心bug:587端口必须启用TLS)
954
- print(f"🔌 正在连接SMTP服务器 {smtp_host}:{smtp_port}...")
955
- with smtplib.SMTP(smtp_host, smtp_port, timeout=120) as smtp:
956
- smtp.starttls() # 587端口强制启用TLS,绝大多数服务器要求
957
- smtp.login(sender_email, sender_password)
958
- print(f"🔐 SMTP服务器登录成功")
959
-
960
- # 所有收件人去重,避免重复发送
961
- all_recipients = list(set(to_emails + cc_emails + bcc_emails))
962
- smtp.sendmail(sender_email, all_recipients, msg.as_string())
963
-
964
- # 12. 发送成功:控制台打印+日志(和旧版完全对齐)
965
- success_msg = f"✅ 邮件发送成功 | 主题:{subject} | 收件人:{len(to_emails)}人"
966
- if cc_emails:
967
- success_msg += f" | 抄送:{len(cc_emails)}人"
968
- if bcc_emails:
969
- success_msg += f" | 密送:{len(bcc_emails)}人"
970
- if valid_attachments:
971
- success_msg += f" | 附件:{len(valid_attachments)}个"
909
+ # 7. 循环重试发送(解决网络超时/抖动)
910
+ for retry_idx in range(1, self.MAIL_RETRY_TIMES + 1):
911
+ try:
912
+ # 8. 构建邮件对象
913
+ msg = MIMEMultipart()
914
+ msg['From'] = self.SMTP_SENDER
915
+ msg['To'] = ', '.join(to_emails)
916
+ if cc_emails:
917
+ msg['Cc'] = ', '.join(cc_emails)
918
+ if bcc_emails:
919
+ msg['Bcc'] = ', '.join(bcc_emails)
920
+ msg['Subject'] = subject
921
+
922
+ # 9. 邮件正文
923
+ body = MIMEText(html_body, 'html', 'utf-8')
924
+ msg.attach(body)
925
+
926
+ # 10. 附件处理 + 安全解码 + 中文文件名修复
927
+ valid_attachments = []
928
+ for attachment in attachments:
929
+ attachment = attachment.strip()
930
+ if not os.path.exists(attachment):
931
+ error_msg = f"❌ 邮件发送失败:附件不存在 -> {attachment}"
932
+ self.logger.error(error_msg)
933
+ print(error_msg)
934
+ raise FileNotFoundError(error_msg)
935
+
936
+ file_name = os.path.basename(attachment)
937
+ mime_type = get_mime_type(attachment)
938
+
939
+ # 二进制读取,避免大文件/编码报错
940
+ try:
941
+ with open(attachment, 'rb') as file:
942
+ file_content = file.read()
943
+ except Exception as e:
944
+ err = f"❌ 读取附件失败 {attachment}:{str(e)}"
945
+ self.logger.error(err, exc_info=True)
946
+ print(err)
947
+ raise RuntimeError(err)
948
+
949
+ # 构造附件
950
+ if mime_type.startswith('image/'):
951
+ part = MIMEImage(file_content, _subtype=mime_type.split('/')[1])
952
+ elif mime_type in ('text/plain', 'text/csv'):
953
+ # 文本文件容错解码
954
+ text = file_content.decode("utf-8", errors="replace")
955
+ part = MIMEText(text, _subtype=mime_type.split('/')[1], _charset='utf-8')
956
+ else:
957
+ part = MIMEApplication(file_content, _subtype=mime_type.split('/')[1])
958
+
959
+ # 修复中文附件名乱码(RFC2231标准)
960
+ part.add_header('Content-Disposition', 'attachment', filename=file_name)
961
+ part.set_param("filename*", f"utf-8''{file_name}", header="Content-Disposition")
962
+ part['Content-Type'] = f'{mime_type}'
963
+ msg.attach(part)
964
+
965
+ valid_attachments.append(file_name)
966
+ self.logger.debug(f"已添加附件: {file_name}")
967
+ print(f"✅ 已添加附件: {file_name}")
968
+
969
+ # 11. 连接SMTP服务器(延长超时 + 双重ehlo提升兼容性)
970
+ print(f"🔌 第{retry_idx}次尝试连接 SMTP {self.SMTP_HOST}:{self.SMTP_PORT}")
971
+ self.logger.info(f"第{retry_idx}次连接 SMTP 服务器")
972
+
973
+ with smtplib.SMTP(self.SMTP_HOST, self.SMTP_PORT, timeout=self.SMTP_TIMEOUT) as smtp:
974
+ smtp.ehlo()
975
+ smtp.starttls()
976
+ smtp.ehlo()
977
+ smtp.login(self.SMTP_SENDER, self.SMTP_PWD)
978
+ print(f"🔐 SMTP服务器登录成功")
979
+
980
+ smtp.sendmail(self.SMTP_SENDER, all_recipients, msg.as_string())
981
+
982
+ # 发送成功
983
+ success_msg = f"✅ 邮件发送成功 | 主题:{subject} | 收件人:{len(to_emails)}人"
984
+ if cc_emails:
985
+ success_msg += f" | 抄送:{len(cc_emails)}人"
986
+ if bcc_emails:
987
+ success_msg += f" | 密送:{len(bcc_emails)}人"
988
+ if valid_attachments:
989
+ success_msg += f" | 附件:{len(valid_attachments)}个"
990
+
991
+ self.logger.info(success_msg)
992
+ print(success_msg)
993
+ return True
972
994
 
973
- self.logger.info(success_msg)
974
- print(success_msg)
975
- return True
995
+ # 可重试异常:超时、连接断开
996
+ except (TimeoutError, smtplib.SMTPServerDisconnected) as e:
997
+ last_exception = e
998
+ err = f"⚠️ 第{retry_idx}次发送超时/连接断开:{str(e)}"
999
+ self.logger.warning(err)
1000
+ print(err)
1001
+ if retry_idx < self.MAIL_RETRY_TIMES:
1002
+ print(f"⏳ {self.MAIL_RETRY_INTERVAL} 秒后进行重试...")
1003
+ time.sleep(self.MAIL_RETRY_INTERVAL)
1004
+ continue
1005
+
1006
+ # 账号密码错误:致命异常,直接终止重试
1007
+ except smtplib.SMTPAuthenticationError:
1008
+ err_msg = "❌ 邮件发送失败:SMTP账号/密码错误,终止重试"
1009
+ self.logger.error(err_msg, exc_info=True)
1010
+ print(err_msg)
1011
+ raise ValueError(err_msg)
976
1012
 
977
- # 13. 分类异常捕获(和旧版对齐,易排查问题)
978
- except smtplib.SMTPAuthenticationError:
979
- err_msg = "❌ 邮件发送失败:SMTP账号/密码/授权码错误"
980
- self.logger.error(err_msg, exc_info=True)
981
- print(err_msg)
982
- raise ValueError(err_msg)
983
- except smtplib.SMTPConnectError:
984
- err_msg = "❌ 邮件发送失败:SMTP服务器连接失败(检查host/port/防火墙/网络)"
985
- self.logger.error(err_msg, exc_info=True)
986
- print(err_msg)
987
- raise ConnectionError(err_msg)
988
- except smtplib.SMTPException as e:
989
- err_msg = f"❌ 邮件发送失败:SMTP协议错误 - {str(e)}"
990
- self.logger.error(err_msg, exc_info=True)
991
- print(err_msg)
992
- raise RuntimeError(err_msg)
993
- except FileNotFoundError:
994
- raise # 附件错误已提前处理,直接抛出
995
- except Exception as e:
996
- err_msg = f"❌ 邮件发送失败:{str(e)}"
997
- self.logger.error(err_msg, exc_info=True)
998
- print(err_msg)
999
- raise RuntimeError(err_msg)
1013
+ # 连接失败
1014
+ except smtplib.SMTPConnectError:
1015
+ err_msg = "❌ 邮件发送失败:SMTP服务器连接失败(检查网络/防火墙)"
1016
+ self.logger.error(err_msg, exc_info=True)
1017
+ print(err_msg)
1018
+ raise ConnectionError(err_msg)
1019
+
1020
+ # 其他SMTP协议异常
1021
+ except smtplib.SMTPException as e:
1022
+ err_msg = f"❌ 邮件发送失败:SMTP协议错误 - {str(e)}"
1023
+ self.logger.error(err_msg, exc_info=True)
1024
+ print(err_msg)
1025
+ raise RuntimeError(err_msg)
1026
+
1027
+ # 文件类异常,直接抛出
1028
+ except (FileNotFoundError, RuntimeError):
1029
+ raise
1030
+
1031
+ # 通用未知异常
1032
+ except Exception as e:
1033
+ last_exception = e
1034
+ err = f"⚠️ 第{retry_idx}次发送未知异常:{str(e)}"
1035
+ self.logger.error(err, exc_info=True)
1036
+ print(err)
1037
+ if retry_idx < self.MAIL_RETRY_TIMES:
1038
+ time.sleep(self.MAIL_RETRY_INTERVAL)
1039
+ continue
1040
+
1041
+ # 所有重试全部失败
1042
+ final_err = f"❌ 邮件{self.MAIL_RETRY_TIMES}次重试全部失败,最终异常:{str(last_exception)}"
1043
+ self.logger.error(final_err, exc_info=True)
1044
+ print(final_err)
1045
+ raise RuntimeError(final_err)
1000
1046
 
1001
1047
  # -------------------------- Excel格式化 --------------------------
1002
1048
  def format_excel_worksheet(self, worksheet, df, workbook):
@@ -1687,28 +1733,38 @@ class DataProcessingAndMessaging:
1687
1733
  self.logger.warning(f"关闭Excel进程时发生异常: {str(e)}")
1688
1734
 
1689
1735
  # -------------------------- 上传文件/DF到内网文件服务器(最终完整版) --------------------------
1690
- def upload_to_internal_server(self, input_data, filename_in_server: str = "dataframe_result.xlsx"):
1736
+ # -------------------------- 上传文件/DF到内网文件服务器(带可控自动下载最终版) --------------------------
1737
+ def upload_to_internal_server(self, input_data, filename_in_server: str = "dataframe_result.xlsx",
1738
+ auto_download: bool = False, download_save_path: str = None):
1691
1739
  """
1692
- 上传数据到内网 http://fs-cc.xin.com(按要求定制:重试3次、读超时5分钟,无拆分无压缩)
1693
- :param input_data: 支持 3 种输入 →
1694
- 1) 单个 DataFrame
1695
- 2) 字典 {sheet名: df} → 自动生成多Sheet Excel
1696
- 3) 本地Excel文件路径(str)
1740
+ 上传数据到内网 http://fs-cc.xin.com(带可控自动下载功能)
1741
+ :param input_data: 支持 3 种输入 → 1) 单个 DataFrame 2) 字典 {sheet名: df} 3) 本地Excel文件路径(str)
1697
1742
  :param filename_in_server: 服务器上显示的文件名
1743
+ :param auto_download: 上传成功后是否自动下载,【默认False=关闭下载】,仅传入True时启动下载
1744
+ :param download_save_path: 下载文件的本地保存路径(可选),默认与日志文件同目录
1698
1745
  :return: 下载链接(失败返回None)
1699
1746
  """
1747
+ import requests
1748
+ import pandas as pd
1749
+ import os
1750
+ import datetime
1751
+ from io import BytesIO
1752
+ from requests.adapters import HTTPAdapter
1753
+ from urllib3.util.retry import Retry
1754
+
1700
1755
  upload_url = "http://fs-cc.xin.com"
1701
1756
  self.logger.info(f"开始上传数据到内网服务器,服务器文件名:{filename_in_server}")
1702
1757
  print(f"📤 正在上传 → 服务器文件名:{filename_in_server}")
1703
1758
 
1704
- # ====================== 【按要求修改:重试固定3次】 ======================
1705
- def create_retry_session(retries=3):
1759
+ # ====================== 【完全保留原有配置:重试3次、读超时5分钟】 ======================
1760
+ def create_retry_session(retries=3, allowed_methods=None):
1761
+ allowed_methods = allowed_methods or ["POST"]
1706
1762
  session = requests.Session()
1707
1763
  retry_strategy = Retry(
1708
1764
  total=retries,
1709
1765
  backoff_factor=2,
1710
1766
  status_forcelist=[500, 502, 503, 504, 408],
1711
- allowed_methods=["POST"],
1767
+ allowed_methods=allowed_methods,
1712
1768
  raise_on_status=False
1713
1769
  )
1714
1770
  adapter = HTTPAdapter(max_retries=retry_strategy)
@@ -1718,9 +1774,48 @@ class DataProcessingAndMessaging:
1718
1774
 
1719
1775
  # ======================================================================
1720
1776
 
1777
+ # ====================== 【新增:自动下载核心函数(与上传逻辑完全对齐)】 ======================
1778
+ def _auto_download_file(download_url, save_path, file_name):
1779
+ """内部自动下载函数,带重试保障、流式下载、日志同步"""
1780
+ try:
1781
+ # 自动创建保存目录,不存在则新建
1782
+ os.makedirs(save_path, exist_ok=True)
1783
+ full_save_path = os.path.join(save_path, file_name)
1784
+
1785
+ self.logger.info(f"📥 启动自动下载,文件保存路径:{full_save_path}")
1786
+ print(f"📥 启动自动下载,文件保存路径:{full_save_path}")
1787
+
1788
+ # 流式下载(支持大文件,避免内存溢出),带3次重试、5分钟超时
1789
+ session = create_retry_session(retries=3, allowed_methods=["GET"])
1790
+ response = session.get(download_url, timeout=(10, 300), stream=True)
1791
+
1792
+ if response.status_code == 200:
1793
+ # 分块写入文件
1794
+ with open(full_save_path, 'wb') as f:
1795
+ for chunk in response.iter_content(chunk_size=8192):
1796
+ if chunk:
1797
+ f.write(chunk)
1798
+
1799
+ self.logger.info(f"✅ 自动下载成功,文件已保存至:{full_save_path}")
1800
+ print(f"✅ 自动下载成功,文件已保存至:{full_save_path}")
1801
+ return full_save_path
1802
+ else:
1803
+ err_msg = f"❌ 自动下载失败,服务器响应状态码:{response.status_code}"
1804
+ self.logger.error(err_msg)
1805
+ print(err_msg)
1806
+ return None
1807
+
1808
+ except Exception as e:
1809
+ err_msg = f"❌ 自动下载异常:{str(e)}"
1810
+ self.logger.error(err_msg, exc_info=True)
1811
+ print(err_msg)
1812
+ return None
1813
+
1814
+ # ======================================================================
1815
+
1721
1816
  try:
1722
1817
  # ==============================================
1723
- # 【完全保留原逻辑:无Sheet拆分、无ZIP压缩】
1818
+ # 【100%完全保留原有上传逻辑:无Sheet拆分、无ZIP压缩】
1724
1819
  # ==============================================
1725
1820
  if isinstance(input_data, dict):
1726
1821
  # 字典 → 多Sheet Excel
@@ -1759,25 +1854,23 @@ class DataProcessingAndMessaging:
1759
1854
  else:
1760
1855
  raise ValueError(f"不支持输入类型:{type(input_data)}")
1761
1856
 
1762
- # 上传
1857
+ # 上传执行
1763
1858
  session = create_retry_session()
1764
1859
  files = {"file": (filename_in_server, file_obj, file_type)}
1765
- # ====================== 【按要求修改:读超时改为5分钟(300秒)】 ======================
1766
1860
  response = session.post(upload_url, files=files, timeout=(10, 600))
1767
- # ======================================================================
1768
1861
 
1769
1862
  # 关闭文件
1770
1863
  if isinstance(input_data, str):
1771
1864
  file_obj.close()
1772
1865
 
1773
- # 结果处理
1866
+ # 上传结果处理
1774
1867
  if response.status_code == 200:
1775
1868
  download_url = response.text.strip()
1776
- self.logger.info(f"✅ 上传成功,链接:{download_url}")
1869
+ self.logger.info(f"✅ 上传成功,下载链接:{download_url}")
1777
1870
  print("✅ 上传成功!")
1778
1871
  print("🔗 下载地址:", download_url)
1779
1872
 
1780
- # 生成同名链接文件(完全保留原逻辑)
1873
+ # 生成同名链接文件(完全保留原有逻辑)
1781
1874
  file_base_name = os.path.splitext(filename_in_server)[0]
1782
1875
  link_file_name = f"{file_base_name}.log"
1783
1876
  link_path = os.path.join(os.path.dirname(self.main_log_file), link_file_name)
@@ -1789,10 +1882,19 @@ class DataProcessingAndMessaging:
1789
1882
  f.write(file_content)
1790
1883
 
1791
1884
  self.logger.info(f"上传链接已保存到:{link_path}")
1885
+
1886
+ # ====================== 【核心:仅当auto_download=True时,才启动自动下载】 ======================
1887
+ if auto_download:
1888
+ # 下载路径优先级:用户自定义路径 > 默认日志文件同目录
1889
+ final_save_path = download_save_path if download_save_path else os.path.dirname(self.main_log_file)
1890
+ # 执行自动下载
1891
+ _auto_download_file(download_url, final_save_path, filename_in_server)
1892
+ # ======================================================================
1893
+
1792
1894
  return download_url
1793
1895
 
1794
1896
  else:
1795
- err = f"❌ 上传失败,状态码:{response.status_code}"
1897
+ err = f"❌ 上传失败,服务器响应状态码:{response.status_code}"
1796
1898
  self.logger.error(err)
1797
1899
  print(err)
1798
1900
  return None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Functions_d
3
- Version: 1.34
3
+ Version: 1.35
4
4
  Summary: 包含数据处理、Hive交互、企业微信消息发送、Excel操作等功能的工具类库
5
5
  Author: DongYang
6
6
  Author-email: 649898871@qq.com
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Functions_d
3
- Version: 1.34
3
+ Version: 1.35
4
4
  Summary: 包含数据处理、Hive交互、企业微信消息发送、Excel操作等功能的工具类库
5
5
  Author: DongYang
6
6
  Author-email: 649898871@qq.com
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = Functions_d
3
- version = 1.34
3
+ version = 1.35
4
4
  author = DongYang
5
5
  author_email = 649898871@qq.com
6
6
  description = 包含数据处理、Hive交互、企业微信消息发送、Excel操作等功能的工具类库
File without changes
File without changes
File without changes