ZhuLinsen/daily_stock_analysis · error · ValueError

文件超过 MB 限制

Error message

文件超过 {MAX_FILE_BYTES // (1024 * 1024)}MB 限制

What it means

Guard in parse_import_from_bytes: uploaded file exceeds MAX_FILE_BYTES (2MB). Enforced before any format sniffing to bound parser memory use.

Solutions

  1. Trim the file to only the needed columns (code, name) before import
  2. For CSV, strip headers/extra columns; for xlsx, save as CSV of just the code column
  3. Compress workflow: paste text instead (parse_import_from_text allows 100KB) or split into batches

Example fix

# before
items = parse_import_from_bytes(open('portfolio.xlsx','rb').read(), 'portfolio.xlsx')  # >2MB
# after: extract just the code column to CSV first
items = parse_import_from_bytes(csv_only_bytes, 'portfolio.csv')
Defensive patterns

Strategy: validation

Validate before calling

from src.services.import_parser import MAX_FILE_BYTES
if len(data) > MAX_FILE_BYTES:
    raise ValueError(f'文件过大,请精简到 {MAX_FILE_BYTES // (1024*1024)}MB 以内(仅保留代码/名称列)')

Type guard

def within_file_limit(b: bytes) -> bool:
    return len(b) <= 2 * 1024 * 1024

Prevention

When it happens

Trigger: Uploading a CSV/XLSX import file larger than 2MB; exporting a full watchlist with names and extra columns.

Common situations: Large broker exports; xlsx with embedded formatting/images inflating size; pasting whole portfolio history instead of the code column.

Related errors


AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15). Data as JSON: /api/errors/ff8cd2199f5783a7. Report an issue: GitHub.

Appendix: source

Thrown at src/services/import_parser.py:143

    return result


def parse_import_from_bytes(data: bytes, filename: Optional[str] = None) -> List[Tuple[Optional[str], Optional[str], str]]:
    """
    Parse file bytes (CSV/Excel) into items.

    Args:
        data: File content bytes.
        filename: Optional filename for format detection (e.g. "a.csv", "b.xlsx").

    Returns:
        List of (code, name, confidence); code may be None if resolution failed.

    Raises:
        ValueError: On parse error or unsupported format.
    """
    if len(data) > MAX_FILE_BYTES:
        raise ValueError(f"文件超过 {MAX_FILE_BYTES // (1024 * 1024)}MB 限制")

    ext = ""
    if filename:
        ext = "." + filename.rsplit(".", 1)[-1].lower() if "." in filename else ""
    logger.debug(f"[ImportParser] 开始解析文件: filename={filename or '-'}, ext={ext or '-'}, bytes={len(data)}")

    looks_like_zip = len(data) >= 4 and data[:4] == b"PK\x03\x04"

    # Excel: .xlsx (or zip magic)
    if ext == ".xlsx" or looks_like_zip:
        try:
            # Use header=None to avoid silently consuming the first data row as column names
            # when the sheet has no header row. We detect headers the same way as the CSV path.
            df = pd.read_excel(io.BytesIO(data), sheet_name=0, engine="openpyxl", header=None, dtype=str)
            if df is None or df.empty:
                return []
            df = df.fillna("")
            first_row = [str(x).strip().lower() for x in df.iloc[0].tolist()]

View on GitHub (pinned to 5159bd72e8)