欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python?Flask中文件與異常處理的實(shí)踐指南

 更新時(shí)間:2025年05月20日 08:24:00   作者:碼農(nóng)阿豪@新空間  
在開(kāi)發(fā)Web應(yīng)用時(shí),文件處理和異常處理是常見(jiàn)的需求,本文將通過(guò)一個(gè)實(shí)際案例,分析如何優(yōu)化Python?Flask應(yīng)用中的文件處理邏輯,感興趣的小伙伴可以了解下

引言

在開(kāi)發(fā)Web應(yīng)用時(shí),文件處理和異常處理是常見(jiàn)的需求。特別是在使用Flask框架進(jìn)行文件上傳、處理和下載時(shí),正確處理返回值類型和異常情況至關(guān)重要。本文將通過(guò)一個(gè)實(shí)際案例,分析如何優(yōu)化Python Flask應(yīng)用中的文件處理邏輯,并解決常見(jiàn)的異常問(wèn)題。

問(wèn)題背景

在一個(gè)基于Flask的文件處理工具中,用戶上傳Excel文件,系統(tǒng)處理后返回結(jié)果文件。但在實(shí)際運(yùn)行中,出現(xiàn)了以下錯(cuò)誤:

AttributeError: 'list' object has no attribute 'read'

該錯(cuò)誤表明,F(xiàn)lask的 send_file 方法期望接收一個(gè)文件路徑(字符串),但實(shí)際傳入的是一個(gè)列表(list),導(dǎo)致無(wú)法讀取文件內(nèi)容。

此外,還出現(xiàn)了以下日志:

2025-05-20 01:05:37,500 - ERROR - process_and_export_results 返回了無(wú)效類型

這說(shuō)明后端處理函數(shù)的返回值類型不符合預(yù)期,導(dǎo)致后續(xù)操作失敗。

問(wèn)題分析

1. 錯(cuò)誤原因

process_single_thread 函數(shù)返回的是 [output_file](包含單個(gè)文件路徑的列表),但 send_file 需要的是 output_file(字符串)。

調(diào)用方未對(duì)返回值進(jìn)行類型檢查,直接傳給 send_file,導(dǎo)致 AttributeError。

2. 深層原因

接口設(shè)計(jì)不一致:處理函數(shù)返回列表,但調(diào)用方期望字符串。

異常處理不足:未對(duì)返回值做校驗(yàn),導(dǎo)致錯(cuò)誤傳播到Flask中間件。

日志信息不完整:錯(cuò)誤日志未能清晰指出問(wèn)題所在。

解決方案

1. 優(yōu)化 process_single_thread 返回值

原代碼:

def process_single_thread(raw_results, cookie, timestamp, base_filename, secretKey, receiver_email):
    # ...處理邏輯...
    return [output_file]  # 返回列表

優(yōu)化后:

def process_single_thread(raw_results, cookie, timestamp, base_filename, secretKey, receiver_email):
    """單線程處理數(shù)據(jù)

    Args:
        raw_results: 待處理的原始數(shù)據(jù)列表
        cookie: 用于處理的cookie
        timestamp: 時(shí)間戳,用于生成文件名
        base_filename: 基礎(chǔ)文件名
        receiver_email: 接收結(jié)果的郵箱地址

    Returns:
        str: 輸出文件路徑(直接返回字符串,而非列表)
    """
    # ...處理邏輯...
    return output_file  # 直接返回字符串

優(yōu)化點(diǎn):

  • 修改返回值為字符串,符合 send_file 的預(yù)期。
  • 更新函數(shù)文檔,明確返回值類型。

2. 調(diào)用方增強(qiáng)校驗(yàn)

在 app.py 中,增加對(duì)返回值的檢查:

try:
    output_file = process_and_export_results(filepath, cookie, nationwide, receiver_email)
    
    # 檢查返回值是否為有效路徑
    if not isinstance(output_file, str):
        logger.error(f"無(wú)效返回值類型: {type(output_file)}")
        return "處理錯(cuò)誤:內(nèi)部服務(wù)異常", 500
    
    if not os.path.exists(output_file):
        logger.error(f"文件不存在: {output_file}")
        return "處理錯(cuò)誤:結(jié)果文件未生成", 500
    
    return send_file(output_file, as_attachment=True, download_name='result.xlsx')

except Exception as e:
    logger.error(f"文件處理異常: {str(e)}", exc_info=True)
    return f"處理錯(cuò)誤:{str(e)}", 500

優(yōu)化點(diǎn):

  • 檢查返回值是否為字符串。
  • 確保文件存在,避免 FileNotFoundError。
  • 捕獲并記錄異常,返回友好的錯(cuò)誤信息。

3. 日志優(yōu)化

在關(guān)鍵步驟添加詳細(xì)日志,便于排查問(wèn)題:

logger.info(f"開(kāi)始處理文件: {filepath}")
logger.info(f"全國(guó)匹配模式: {'開(kāi)啟' if nationwide else '關(guān)閉'}")
logger.info(f"接收郵箱: {receiver_email}")

output_file = process_and_export_results(filepath, cookie, nationwide, receiver_email)
logger.info(f"處理完成,輸出文件: {output_file}")

完整優(yōu)化后的代碼

deal_excel_file.py(優(yōu)化后)

import os
import logging
from datetime import datetime

logger = logging.getLogger(__name__)

def process_single_thread(raw_results, cookie, timestamp, base_filename, secretKey, receiver_email):
    """單線程處理數(shù)據(jù),返回文件路徑(字符串)"""
    final_results = []
    total_count = len(raw_results)
    success_count = 0

    for idx, item in enumerate(raw_results, 1):
        record = process_single_item(item, idx, cookie, secretKey, False)
        final_results.append(record)
        if record["匹配狀態(tài)"] == "成功":
            success_count += 1

    success_rate = (success_count / total_count) * 100 if total_count > 0 else 0
    output_file = f"result_{timestamp}_{base_filename}.xlsx"

    logger.info(
        f"[{base_filename}] 處理完成 - 總數(shù): {total_count}, "
        f"成功: {success_count}, 失敗: {total_count - success_count}, "
        f"成功率: {success_rate:.2f}%"
    )

    export_to_excel(final_results, output_file)

    if receiver_email:
        try:
            send_email_with_attachment(output_file, receiver_email)
            logger.info(f"[{base_filename}] 結(jié)果已發(fā)送至郵箱: {receiver_email}")
        except Exception as e:
            logger.error(f"[{base_filename}] 郵件發(fā)送失敗: {str(e)}")

    return output_file  # 直接返回字符串

app.py(優(yōu)化后)

from flask import Flask, request, send_file
import os
import logging

app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = 'uploads'
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    handlers=[logging.FileHandler('app.log'), logging.StreamHandler()]
)
logger = logging.getLogger(__name__)

@app.route('/', methods=['POST'])
def upload_file():
    try:
        cookie = request.form.get('cookie', '').strip()
        nationwide = request.form.get('nationwide') == '1'
        receiver_email = request.form.get('email', '').strip()

        logger.info(f"開(kāi)始處理請(qǐng)求,Cookie: {cookie[:10]}...")  # 避免日志泄露完整Cookie

        if not cookie:
            return "請(qǐng)?zhí)峁┯行У腃ookie", 400

        # 檢查文件上傳
        if 'file' not in request.files:
            return "未上傳文件", 400

        file = request.files['file']
        if not file.filename.endswith('.xlsx'):
            return "僅支持.xlsx文件", 400

        # 保存上傳文件
        timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
        filepath = os.path.join(app.config['UPLOAD_FOLDER'], f'upload_{timestamp}.xlsx')
        file.save(filepath)

        # 處理文件
        output_file = process_and_export_results(filepath, cookie, nationwide, receiver_email)

        # 校驗(yàn)返回值
        if not isinstance(output_file, str):
            logger.error(f"無(wú)效的返回值類型: {type(output_file)}")
            return "內(nèi)部服務(wù)錯(cuò)誤", 500

        if not os.path.exists(output_file):
            logger.error(f"文件不存在: {output_file}")
            return "結(jié)果文件生成失敗", 500

        return send_file(output_file, as_attachment=True, download_name='result.xlsx')

    except Exception as e:
        logger.error(f"處理請(qǐng)求時(shí)出錯(cuò): {str(e)}", exc_info=True)
        return f"服務(wù)器錯(cuò)誤: {str(e)}", 500

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

總結(jié)

關(guān)鍵優(yōu)化點(diǎn)

1.統(tǒng)一返回值類型:確保處理函數(shù)返回字符串路徑,而非列表。

2.增強(qiáng)異常處理:

  • 檢查文件是否存在。
  • 捕獲并記錄異常,避免500錯(cuò)誤直接暴露給用戶。

3.完善日志:

  • 關(guān)鍵步驟記錄日志。
  • 避免敏感信息(如完整Cookie)泄露。

最佳實(shí)踐

  • 接口設(shè)計(jì)一致性:函數(shù)返回值應(yīng)符合調(diào)用方預(yù)期。
  • 防御性編程:對(duì)輸入、返回值進(jìn)行校驗(yàn)。
  • 詳細(xì)日志:便于快速定位問(wèn)題。

通過(guò)以上優(yōu)化,系統(tǒng)能更穩(wěn)定地處理文件,并提供清晰的錯(cuò)誤信息,提升用戶體驗(yàn)。

到此這篇關(guān)于Python Flask中文件與異常處理的實(shí)踐指南的文章就介紹到這了,更多相關(guān)Python Flask應(yīng)用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解python3中socket套接字的編碼問(wèn)題解決

    詳解python3中socket套接字的編碼問(wèn)題解決

    本篇文章主要介紹了詳解python3中socket套接字的編碼問(wèn)題解決,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • 詳解Python中type與object的恩怨糾葛

    詳解Python中type與object的恩怨糾葛

    估計(jì)很多人都會(huì)有這樣一個(gè)困惑,object?的類型是?type,但它同時(shí)又是?type?的基類,這是怎么做到的?帶著這個(gè)疑問(wèn),我們開(kāi)始本文的內(nèi)容
    2023-04-04
  • python通過(guò)pip更新所有已安裝的包實(shí)現(xiàn)方法

    python通過(guò)pip更新所有已安裝的包實(shí)現(xiàn)方法

    下面小編就為的帶來(lái)一篇python通過(guò)pip更新所有已安裝的包實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-05-05
  • Macbook安裝Python最新版本、GUI開(kāi)發(fā)環(huán)境、圖像處理、視頻處理環(huán)境詳解

    Macbook安裝Python最新版本、GUI開(kāi)發(fā)環(huán)境、圖像處理、視頻處理環(huán)境詳解

    這篇文章主要介紹了Macbook安裝Python最新版本(3.6.4)、GUI開(kāi)發(fā)環(huán)境、圖像處理、視頻處理環(huán)境詳解,需要的朋友可以參考下
    2020-02-02
  • python命令行工具Click快速掌握

    python命令行工具Click快速掌握

    這篇文章主要介紹了python命令行工具Click快速掌握,寫(xiě) Python 的經(jīng)常要寫(xiě)一些命令行工具,雖然標(biāo)準(zhǔn)庫(kù)提供有命令行解析工具 Argparse,但是寫(xiě)起來(lái)非常麻煩,我很少會(huì)使用它。命令行工具中用起來(lái)最爽的就是 Click,,需要的朋友可以參考下
    2019-07-07
  • python中if和elif的區(qū)別介紹

    python中if和elif的區(qū)別介紹

    這篇文章主要介紹了python中if和elif的區(qū)別,下面文章將舉多個(gè)例子圍繞if和eli的相關(guān)資料展開(kāi)內(nèi)容,需要的朋友可以參考一下,希望對(duì)你有所幫助
    2021-11-11
  • Python函數(shù)中參數(shù)是傳遞值還是引用詳解

    Python函數(shù)中參數(shù)是傳遞值還是引用詳解

    這篇文章主要介紹了深入了解Python函數(shù)中參數(shù)是傳值還是傳引用,在 C/C++ 中,傳值和傳引用是函數(shù)參數(shù)傳遞的兩種方式,在Python中參數(shù)是如何傳遞的,需要的朋友可以參考下
    2019-07-07
  • Python編寫(xiě)繪圖系統(tǒng)之從文本文件導(dǎo)入數(shù)據(jù)并繪圖

    Python編寫(xiě)繪圖系統(tǒng)之從文本文件導(dǎo)入數(shù)據(jù)并繪圖

    這篇文章主要為大家詳細(xì)介紹了Python如何編寫(xiě)一個(gè)繪圖系統(tǒng),可以實(shí)現(xiàn)從文本文件導(dǎo)入數(shù)據(jù)并繪圖,文中的示例代碼講解詳細(xì),感興趣的可以了解一下
    2023-08-08
  • 利用python爬取散文網(wǎng)的文章實(shí)例教程

    利用python爬取散文網(wǎng)的文章實(shí)例教程

    這篇文章主要跟大家介紹了利用python爬取散文網(wǎng)文章的相關(guān)資料,文中介紹的非常詳細(xì),對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧。
    2017-06-06
  • 使用Selenium破解新浪微博的四宮格驗(yàn)證碼

    使用Selenium破解新浪微博的四宮格驗(yàn)證碼

    今天小編就為大家分享一篇關(guān)于使用Selenium破解新浪微博的四宮格驗(yàn)證碼的文章,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2018-10-10

最新評(píng)論