Python脚本如何同时将stdout、stderr输出至文件与屏幕?
解决Python FTP文件传输的日志双输出与错误追踪问题
我来帮你实现这个需求——既要让日志同时显示在屏幕和文件,又要在成功/失败时分别生成对应日志,还得捕获完整的错误回溯信息。下面是完整的实现方案:
完整代码示例
import ftplib import logging import traceback import sys from datetime import datetime def setup_logging(): """配置日志:同时输出到屏幕和过程日志文件""" logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s', handlers=[ logging.StreamHandler(sys.stdout), # 屏幕输出 logging.FileHandler('ftp_process.log', encoding='utf-8') # 过程日志文件 ] ) def write_status_log(success, host, local_file, remote_file, error_msg=None, traceback_str=None): """生成成功/失败状态日志文件""" timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S') if success: with open('OK.log', 'w', encoding='utf-8') as f: f.write(f"=== 文件上传成功 ===\n") f.write(f"时间: {timestamp}\n") f.write(f"FTP服务器: {host}\n") f.write(f"本地文件路径: {local_file}\n") f.write(f"远程文件路径: {remote_file}\n") logging.info("状态日志已生成:OK.log") else: with open('error.log', 'w', encoding='utf-8') as f: f.write(f"=== 文件上传失败 ===\n") f.write(f"时间: {timestamp}\n") f.write(f"FTP服务器: {host}\n") f.write(f"本地文件路径: {local_file}\n") f.write(f"远程文件路径: {remote_file}\n") f.write(f"错误信息: {error_msg}\n") if traceback_str: f.write(f"\n完整错误回溯:\n{traceback_str}") logging.error("状态日志已生成:error.log") def ftp_upload(host, username, password, local_file, remote_file): """核心FTP上传函数""" ftp_conn = None try: logging.info(f"开始连接FTP服务器: {host}") ftp_conn = ftplib.FTP(host) ftp_conn.login(username, password) logging.info(f"成功登录FTP服务器: {host}") # 开启被动模式(大多数场景需要) ftp_conn.set_pasv(True) logging.info(f"开始上传文件: {local_file} -> {remote_file}") with open(local_file, 'rb') as file_obj: # 使用storbinary传输二进制文件(如图片、压缩包),如果是文本文件可以用storlines ftp_conn.storbinary(f'STOR {remote_file}', file_obj) logging.info("文件上传完成!") write_status_log(True, host, local_file, remote_file) return True except Exception as e: tb_str = traceback.format_exc() error_msg = str(e) logging.error(f"上传失败: {error_msg}") logging.error(f"完整错误回溯:\n{tb_str}") write_status_log(False, host, local_file, remote_file, error_msg, tb_str) return False finally: if ftp_conn: try: ftp_conn.quit() logging.info("已断开FTP连接") except Exception as quit_err: logging.warning(f"断开FTP连接时出错: {str(quit_err)}") if __name__ == "__main__": # 初始化日志配置 setup_logging() # 替换成你的FTP参数 FTP_HOST = "your-ftp-server.com" FTP_USER = "your-username" FTP_PASS = "your-password" LOCAL_FILE = "./test_upload.txt" REMOTE_FILE = "/remote/path/test_upload.txt" # 执行上传 ftp_upload(FTP_HOST, FTP_USER, FTP_PASS, LOCAL_FILE, REMOTE_FILE)
代码功能说明
日志双输出
- 通过
setup_logging()函数配置logging模块,同时添加StreamHandler(屏幕输出)和FileHandler(写入ftp_process.log),确保所有操作日志既显示在控制台,又保存到过程日志文件。
- 通过
成功/失败状态日志
- 上传成功时自动生成
OK.log,包含时间、服务器信息、文件路径等关键内容; - 上传失败时生成
error.log,不仅记录错误信息,还会写入完整的Python错误回溯(traceback),方便排查问题。
- 上传成功时自动生成
FTP传输细节
- 开启了被动模式(
set_pasv(True)),这是大多数FTP服务器的要求; - 使用
storbinary传输二进制文件,如果你需要传输纯文本文件,可以替换为storlines; - 在
finally块中确保FTP连接被正确关闭,避免资源泄漏。
- 开启了被动模式(
注意事项
- 参数替换:记得把代码中的FTP主机、用户名、密码、本地/远程文件路径替换成你自己的实际信息;
- 日志覆盖:
OK.log和error.log每次运行会覆盖之前的内容,如果需要追加日志,可以把open的模式从'w'改成'a'; - 文件权限:确保脚本有读取本地文件和写入日志文件的权限;
- 异常捕获:代码捕获了所有异常,如果你需要针对特定FTP错误(如登录失败、文件不存在)做特殊处理,可以单独捕获
ftplib中的异常类(比如ftplib.error_perm)。
内容的提问来源于stack exchange,提问作者Hrvoje T
相关产品推荐
相关产品推荐

