You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python中创建临时文件,供Linux终端执行后自动删除?

解决Python临时文件处理OpenRefine转换规则的问题

问题背景

  • 需求:将Python中的formato_db列表保存为临时文件,通过Linux终端执行OpenRefine客户端命令后自动删除该文件
  • 原实现:使用open()函数保存为transformaciones.json文件
  • 当前问题:使用tempfile.SpooledTemporaryFile()时触发错误:TypeError: 'dict' object cannot be interpreted as an integer

错误原因分析

原代码存在多个核心问题:

  1. 无效类型转换:将formato_db(列表类型)强行转为bytes,json.dump无法直接序列化字节对象,触发类型错误
  2. 临时文件生命周期错误:SpooledTemporaryFile在with块结束后会自动关闭并删除,返回的tfile是已失效的文件对象,无法被后续外部命令调用
  3. 参数传递错误:apply_transformation_db函数需要的是临时文件的路径(供docker容器访问),而非文件对象;且调用时错误传入了formato_db而非生成的临时文件
  4. 工具选型错误:SpooledTemporaryFile没有实际磁盘路径,无法被外部进程(如docker容器)读取,需使用带文件名的临时文件类

修复方案

使用tempfile.NamedTemporaryFile创建带磁盘路径的临时文件,确保外部进程能访问,同时手动控制文件生命周期:

  1. 直接序列化formato_db列表为JSON,跳过无效的字节转换
  2. 配置NamedTemporaryFile为delete=False,避免文件关闭时立即删除
  3. 执行完终端命令后手动删除临时文件,完成自动清理
  4. 修正参数传递逻辑,传入正确的文件路径

完整修正代码

import tempfile
import json
import subprocess
import os

formato_db=[{'op': 'core/column-reorder', 'columnNames': ['\ufeffNúmero de Cliente', '[Account.AccountCode?]', 'CRM Origen', 'Monto inicial', '[ModInitCta?]', '[DeudaRealCuenta?]', '[BillCycleName?]', 'Nombre Campaña', 'Nombre Casa de Cobro', 'Fecha de Asignacion', 'Deuda Gestionable', 'Dirección Completa', 'Fecha Final', 'Email', 'Telefono 1', 'Telefono 2', 'Telefono 3', 'Telefono 4', 'Segmento', '[Documento?]', '[AccStsName?]', 'Ciudad', '[InboxName?]', 'Nombre del Cliente', 'Id de Ejecucion', 'Fecha de Vencimiento', 'Numero Referencia de Pago', 'MIN', 'Plan', 'Precio Subscripcion'], 'description': 'Reorder columns'}, {'op': 'core/column-addition', 'engineConfig': {'facets': [], 'mode': 'row-based'}, 'baseColumnName': 'Telefono 1', 'expression': "join ([coalesce(cells['Telefono 1'].value,''),coalesce(cells['Telefono 2'].value,''),coalesce(cells['Telefono 3'].value,''),coalesce(cells['Telefono 4'].value,'')],' / ')", 'onError': 'keep-original', 'newColumnName': 'Telefonos', 'columnInsertIndex': 15, 'description': "Create column Telefonos at index 15 based on column Telefono 1 using expression join ([coalesce(cells['Telefono 1'].value,''),coalesce(cells['Telefono 2'].value,''),coalesce(cells['Telefono 3'].value,''),coalesce(cells['Telefono 4'].value,'')],' / ')", 'op': 'core/column-reorder', 'columnNames': ['\ufeffNúmero de Cliente', '[Account.AccountCode?]', 'CRM Origen', 'Monto inicial', '[ModInitCta?]', '[DeudaRealCuenta?]', '[BillCycleName?]', 'Nombre Campaña', 'Nombre Casa de Cobro', 'Fecha de Asignacion', 'Deuda Gestionable', 'Dirección Completa', 'Fecha Final', 'Email', 'Telefonos', 'Segmento', '[Documento?]', '[AccStsName?]', 'Ciudad', '[InboxName?]', 'Nombre del Cliente', 'Id de Ejecucion', 'Fecha de Vencimiento', 'Numero Referencia de Pago', 'MIN', 'Plan', 'Precio Subscripcion'], 'description': 'Reorder columns'}, {'op': 'core/column-reorder', 'columnNames': ['\ufeffNúmero de Cliente', '[Account.AccountCode?]', 'CRM Origen', 'Monto inicial', '[ModInitCta?]', '[DeudaRealCuenta?]', '[BillCycleName?]', 'Nombre Campaña', 'Nombre Casa de Cobro', 'Fecha de Asignacion', 'Deuda Gestionable', 'Dirección Completa', 'Fecha Final', 'Email', 'Telefonos', 'Segmento', 'Ciudad', '[InboxName?]', 'Nombre del Cliente', 'Id de Ejecucion', 'Fecha de Vencimiento', 'Numero Referencia de Pago', 'Plan', 'Precio Subscripcion'], 'description': 'Reorder columns'}, {'op': 'core/text-transform', 'engineConfig': {'facets': [], 'mode': 'row-based'}, 'columnName': 'Monto inicial', 'expression': 'value.toNumber()', 'onError': 'keep-original', 'repeat': False, 'repeatCount': 10, 'description': 'Text transform on cells in column Monto inicial using expression value.toNumber()'}, {'op': 'core/text-transform', 'engineConfig': {'facets': [], 'mode': 'row-based'}, 'columnName': 'Dirección Completa', 'expression': 'value.toTitlecase()', 'onError': 'keep-original', 'repeat': False, 'repeatCount': 10, 'description': 'Text transform on cells in column Dirección Completa using expression value.toTitlecase()'}, {'op': 'core/text-transform', 'engineConfig': {'facets': [], 'mode': 'row-based'}, 'columnName': '\ufeffNúmero de Cliente', 'expression': 'grel:value.substring(0, value.length()-2)', 'onError': 'keep-original', 'repeat': False, 'repeatCount': 10, 'description': 'Text transform on cells in column \ufeffNúmero de Cliente using expression grel:value.substring(0, value.length()-2)'}, {'op': 'core/text-transform', 'engineConfig': {'facets': [], 'mode': 'row-based'}, 'columnName': 'Nombre Campaña', 'expression': 'grel:value.substring(4)', 'onError': 'keep-original', 'repeat': False, 'repeatCount': 10, 'description': 'Text transform on cells in column Nombre Campaña using expression grel:value.substring(4)'}]

def get_transformations(formato_db):
    # 创建带.json后缀的临时文件,保留文件名直到手动删除
    with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.json', encoding='utf-8') as tfile:
        json.dump(formato_db, tfile, ensure_ascii=False)
    return tfile.name

def apply_transformation_db(proyecto_id, temp_file_path):
    err = None
    proyecto_id = str(proyecto_id)
    cmd = ['sudo', 'docker', 'run', '--rm', '--network=host', '-v', 
          '/home/ubuntu/api:/data:z', 'felixlohmeier/openrefine-client:v0.3.10', 
          '-H', 'localhost', '--apply', temp_file_path, proyecto_id
    ]
    # 执行命令并捕获错误信息
    result = subprocess.run(cmd, capture_output=True, text=True)
    if result.returncode != 0:
        err = f"命令执行失败: {result.stderr}"
    return err 

# 执行流程
temp_file_path = get_transformations(formato_db)
err_transf_application = apply_transformation_db(proyecto_id, temp_file_path)

# 清理临时文件
os.unlink(temp_file_path)

# 错误处理(可选)
if err_transf_application:
    print(err_transf_application)

关键改动说明

  • 临时文件选型:NamedTemporaryFile生成带磁盘路径的文件,支持外部进程访问;suffix='.json'明确文件类型,适配OpenRefine客户端
  • 序列化优化:ensure_ascii=False保留西班牙语重音等特殊字符,无需额外类型转换
  • 生命周期控制:delete=False避免文件提前删除,执行完命令后用os.unlink手动清理
  • 错误捕获:通过subprocess.run的返回码和stderr捕获命令执行错误,便于排查问题

内容的提问来源于stack exchange,提问作者frankh07

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 01:24:29