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

生成含特殊字符的XML文件时触发OSError无效参数错误求助

解决Windows下文件名含非法字符导致的OSError问题

问题场景

我需要生成两种命名规则的XML文件:

  • 自动命名格式:23-10-2022|21-03-11.xml
  • 用户自定义名称拼接时间格式:userGeneratedName23-10-2022-21-03-11.xml

但程序将文件保存到指定文件夹时抛出Invalid argument错误,最初怀疑是os.path.join使用不当,相关代码及报错信息如下:

相关代码

if not os.path.exists("Generated XMLs"):
    os.makedirs("Generated XMLs")
#open file
today = date.today()
now = datetime.now()
#if filename is not specified, create file with today's date and time of creation
if filename == "":
    filename = today.strftime("%d-%m-%Y") +"|"+ now.strftime("%H-%M-%S")
#if filename is specified,ad at the and of filename today's date and time of creation
else:
    filename = filename + today.strftime("%d-%m-%Y")+"|"+ now.strftime("%H-%M-%S")
# open file wchich is in Generated XMLs folder and name it with variable filename
file = open(os.path.join("Generated XMLs", filename + ".xml"), "w")
#write to file

#write header
file.write("\n<root>\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
file.write("\t<POZYCJE>\n")
#write data
# ask user if he wont netto or brutto meters and ad flag
flag = input("Enter 'n' if you want to use netto meters or 'b' if you want to use brutto meters: ")
for i in range(len(convertedData)):

    file.write("\t\t<POZYCJA>\n")
    file.write("\t\t\t<LP>" + str(i+1) + "</LP>\n")
    file.write("\t\t\t<TOWAR>\n")

    file.write("\t\t\t\t<KOD>" + convertedData[i][0] + " " + convertedData[i][1] + "</KOD>\n")
    file.write("\t\t\t\t<NAZWA>" + convertedData[i][0] + " " + convertedData[i][1] + "</NAZWA>\n")
    file.write("\t\t\t\t<OPIS/>")
    file.write("\t\t\t\t<EAN/>")
    file.write("\t\t\t\t<SWW/>")
    file.write("\t\t\t\t<NUMER_KATALOGOWY/>")
    file.write("\t\t\t\t<MPP>" + "0" + "</MPP>\n")

    file.write("\t\t\t</TOWAR>\n")
    file.write("\t\t\t<STAWKA_VAT>\n")

    file.write("\t\t\t\t<STAWKA>" + "23.00" + "</STAWKA>\n")
    file.write("\t\t\t\t<FLAGA>" + "2" + "</FLAGA>\n")
    file.write("\t\t\t\t<ZRODLOWA>" + "0.00" + "</ZRODLOWA>\n")

    file.write("\t\t\t</STAWKA_VAT>\n")
    file.write("\t\t\t<CENY>\n")

    file.write("\t\t\t\t<CENAZCZTEREMAMIEJSCAMI>0</CENAZCZTEREMAMIEJSCAMI>\n")
    file.write("\t\t\t\t<POCZATKOWA_WAL_CENNIKA>00.0000</POCZATKOWA_WAL_CENNIKA>\n")
    file.write("\t\t\t\t<POCZATKOWA_WAL_DOKUMENTU>00.0000</POCZATKOWA_WAL_DOKUMENTU>\n")
    file.write("\t\t\t\t<PO_RABACIE_WAL_CENNIKA>00.0000</PO_RABACIE_WAL_CENNIKA>\n")
    file.write("\t\t\t\t<PO_RABACIE_PLN>00.0000</PO_RABACIE_PLN>\n")
    file.write("\t\t\t\t<PO_RABACIE_WAL_DOKUMENTU>00.0000</PO_RABACIE_WAL_DOKUMENTU>\n")

    file.write("\t\t\t</CENY>\n")
    file.write("\t\t\t<WALUTA>\n")

    file.write("\t\t\t\t<SYMBOL>PLN</SYMBOL>\n")
    file.write("\t\t\t\t<KURS_L>1.00</KURS_L>\n")
    file.write("\t\t\t\t<KURS_M>1</KURS_M>\n")

    file.write("\t\t\t</WALUTA>\n")
    file.write("\t\t\t<RABAT>0.00</RABAT>\n")
    file.write("\t\t\t<WARTOSC_NETTO>0.00</WARTOSC_NETTO>\n")
    file.write("\t\t\t<WARTOSC_BRUTTO>0.00</WARTOSC_BRUTTO>\n")
    file.write("\t\t\t<WARTOSC_NETTO_WAL>00.00</WARTOSC_NETTO_WAL>\n")
    file.write("\t\t\t<WARTOSC_BRUTTO_WAL>833.94</WARTOSC_BRUTTO_WAL>\n")
    if flag == "n":
        file.write("\t\t\t<ILOSC>" + convertedData[i][3] + "00" + "</ILOSC>\n")
    elif flag == "b":
        file.write("\t\t\t<ILOSC>" + convertedData[i][2] + "00" + "</ILOSC>\n")
    else:
        print("Error: Wrong flag. Enter 'n' or 'b'.")
    file.write("\t\t\t<JB>" + convertedData[i][4] + "</JB>\n")
    file.write("\t\t\t<JM_CALKOWITE>0.00</JM_CALKOWITE>\n")
    file.write("\t\t\t<JM_ZLOZONA>\n")

    file.write("\t\t\t\t\n")
    file.write("\t\t\t\t\n")
    file.write("\t\t\t\t\n")

    file.write("\t\t\t</JM_ZLOZONA>\n")
    file.write("\t\t\t<JMZ>" + convertedData[i][4] + "</JMZ>\n")
    file.write("\t\t\t<JM_PRZELICZNIK_L>1.00</JM_PRZELICZNIK_L>\n")
    file.write("\t\t\t<JM_PRZELICZNIK_M>1</JM_PRZELICZNIK_M>\n")
    file.write("\t\t</POZYCJA>\n")



#write footer
file.write("\t</POZYCJE>\n")
file.write("</root>")
#close file
file.close()

报错信息

Traceback (most recent call last):
  File "C:\Users\reczul\PycharmProjects\pythonProject5\main.py", line 23, in <module>
    main()
  File "C:\Users\reczul\PycharmProjects\pythonProject5\main.py", line 13, in main
    XMLCreator.CreateXML(DataConverter.ConvertData(data))
  File "C:\Users\reczul\PycharmProjects\pythonProject5\venv\Functions\XMLCreator.py", line 20, in CreateXML
    file = open(os.path.join("Generated XMLs", filename + ".xml"), "w")
OSError: [Errno 22] Invalid argument: 'Generated XMLs\\24-10-2022|09-23-45.xml'

Process finished with exit code 1

错误原因

问题和os.path.join无关,核心原因是Windows系统禁止文件名包含竖线|,除此之外,:、*、?、<、>、"这些字符也属于非法字符,都会触发OSError。从报错路径可以看到,文件名里的|是罪魁祸首。

修复方案

1. 替换文件名中的非法竖线

将生成文件名时使用的竖线|替换为合法字符,比如横线-或者下划线_,修改后的代码如下:

替换为横线:

if filename == "":
    filename = today.strftime("%d-%m-%Y") + "-" + now.strftime("%H-%M-%S")
else:
    filename = filename + today.strftime("%d-%m-%Y") + "-" + now.strftime("%H-%M-%S")

替换为下划线(更清晰的分隔):

if filename == "":
    filename = f"{today.strftime('%d-%m-%Y')}_{now.strftime('%H-%M-%S')}"
else:
    filename = f"{filename}{today.strftime('%d-%m-%Y')}_{now.strftime('%H-%M-%S')}"

2. 过滤用户自定义名称中的非法字符

如果允许用户输入自定义文件名,建议提前过滤掉所有Windows非法字符,避免后续报错:

import re

# 匹配所有Windows文件名非法字符的正则表达式
invalid_filename_chars = r'[\\/:*?"<>|]'
# 将非法字符替换为下划线
filename = re.sub(invalid_filename_chars, '_', filename)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 04:30:57