Search code examples
pythonxmloserror

Python OSError 22 in parsing XML file that exists and has valid filename


I'm attempting to parse one or more XML files that are exported from the Bricklink website. I'm opening the file via the defusedxml ElementTree system.

Every file I attempt to open gets me OSError 22 upon the opening attempt, even with what appears to be valid filenames - I can open the files with other tools and can see the contents.

The trace is:

Traceback (most recent call last):
  File "C:\Users\Jason\AppData\Local\Programs\Python\Python38\lib\tkinter\__init__.py", line 1883, in __call__
    return self.func(*args)
  File "D:/Jason/Projects/Projects/wantedlist_modder.py", line 48, in processfiles
    tree = ET.parse(filename)
  File "C:\Users\Jason\AppData\Local\Programs\Python\Python38\lib\site-packages\defusedxml\common.py", line 105, in parse
    return _parse(source, parser)
  File "C:\Users\Jason\AppData\Local\Programs\Python\Python38\lib\xml\etree\ElementTree.py", line 1202, in parse
    tree.parse(source, parser)
  File "C:\Users\Jason\AppData\Local\Programs\Python\Python38\lib\xml\etree\ElementTree.py", line 584, in parse
    source = open(source, "rb")
OSError: [Errno 22] Invalid argument: "'D:/Jason/Downloads/LF_LtN_2020.xml'"

The python code is as follows:

from tkinter import messagebox, filedialog
import tkinter as tk
from defusedxml.ElementTree import *
import defusedxml.ElementTree as ET
import io

class Application(tk.Frame):
    def __init__(self, master=None):
        super().__init__(master)
        self.master = master
        self.pack()
        self.create_widgets()

    def create_widgets(self):
        self.pack(padx = 20, pady = 20)
        frame = Frame(self)
        frame.pack(side = TOP)
        # create variable for input field
        self.filename = tk.StringVar()
        self.filename.set("")
        # create input field
        self.inputfile = tk.Entry(frame)
        self.inputfile.pack(side = LEFT)
        self.inputfile["textvariable"] = self.filename
        # create browse button
        self.browse = tk.Button(frame, text = "Browse...", command = self.openbrowse)
        self.browse.pack(side = LEFT)
        # create process button
        self.process = tk.Button(self, text = "Process", command = self.processfiles)
        self.process.pack(side = TOP, padx = 20, pady = 20)
        # create quit button
        self.quit = tk.Button(self, text = "QUIT", fg = "red", command = self.master.destroy)
        self.quit.pack(side = BOTTOM)

    def openbrowse(self):
        filenames = tk.filedialog.askopenfilenames(title = 'select', filetypes = [("XML", ".xml"),])
        if not filenames is None:
            self.filename.set(', '.join(repr(u) for u in filenames))

    def processfiles(self):
        print("Roger, roger!")
        filenames = tuple(self.filename.get().split(','))
        showdone = 0
        for filename in filenames:
            try:
                print(filename)
                tree = ET.parse(filename)
                showdone = 1
            except FileNotFoundError:
                tk.messagebox.showinfo("Wanted List Modder", "Please enter a valid filename")
        if showdone:
            tk.messagebox.showinfo("Wanted List Modder", "Done!")

root = tk.Tk()
app = Application(master=root)
app.mainloop()

I've done a lot of hunting to try to fix this but none of the fix candidates I've found on this site or elsewhere seem to change what's going on (e.g. I'm parsing from file not string). I'm not sure the contents are an issue, this seems to be something related to the filename - or the way I'm passing it to the parse function. It does print the name of the file it's processing, and I'm using the Browse button system to locate the file. I know that leads to some extra processing converting to/from tuple, but I don't think that's the culprit because the variable value passed to parse is a string.

Running Python 3.8.6 with defusedxml 0.6.0 on a Windows 7-x64 machine... and would really like assistance determining the cause of the OSError please.

Thanks in advance - and apologies if it's something simple! I haven't used Python in a while and I'm battling the adverse neurological effects of chemo...


Solution

  • See below - you have extra " in the file name

    # your code with a bug
    try:
        with open('"c:/temp/a.xml"', 'rb') as f:
            pass
    except OSError:
        print('we have a problem')
    
    # bug was removed - it works
    with open('c:/temp/a.xml', 'rb') as f:
        print('it works')