Vague errors when paths aren't found on Windows

I want to see if anyone agrees with me.

In my day job I use Windows.

Say I had this code.

p = Path(r'C:\Users\steven\Python\test.txt')
with open(p) as f:
    lines = f.readlines()
print(lines)

p = PureWindowsPath(r'C:\Users\steven\Python\test.txt')
with open(p) as f:
    lines = f.readlines()
print(lines)

If test.txt or part of the path does not exist, You will get this error.

No such file or directory: 'C:\\Users\\steven\\Python\\test.txt'

Which can be confusing when you first use Pathlib. When I first used Pathlib, I thought Pathlib was literally interpreting my path as C:\\Users\\steven\\Python\\test.txt'. Which it wasn’t.

Pathlib truly sees the Path and PureWindowsPath as

C:\Users\steven\Python\test.txt'.

So I think when a Path doesn’t exist - the error should look like; (be a one to one)

No such file or directory: 'C:\Users\steven\Python\test.txt'

That is how Linux does it. I think Windows should too. It’s more a convenience and first use thing. After using Pathlib on Windows, you realize to ignore the extra backslashes and just check your path.

Bad suggestion?

EDIT

I understand now it doesn’t come from Pathlib, but I still feel like Python should represent the path correctly in the error.

EDIT 2

Consensus is - the error shouldn’t be a one to one / should show the repr in all instances.

Thanks, learned alot.

This has nothing to do with pathlib, but rather with Python character escaping in string representation, and which method open uses to display the path when constructing the exception.

You’re right.

with open(r'C:\Users\steven\Python\tst.txt') as f:
    lines = f.readlines()
print(lines)

FileNotFoundError: [Errno 2] No such file or directory: 'C:\\Users\\steven\\Python\\test.txt'

But I still feel like the error should represent the path as a one to one. Regardless of where it occurs / comes from.

It does represent it correctly, but it represents it in source code form. What you’re seeing is exactly what happens if you look at the repr of that string:

>>> print(repr(r'C:\Users\steven\Python\tst.txt'))
'C:\\Users\\steven\\Python\\tst.txt'

This notation is dependable and safe for error messages. Printing out the string ifself (rather than its repr) would lead to numerous problems; for example:

>>> path = "c:\regions\new_zealand\tax_data.txt"
>>> print("No such file or directory: " + path)
egionsh file or directory: c:
ew_zealand	ax_data.txt

Is that an improvement? Here’s the same thing with the repr:

>>> print("No such file or directory: " + repr(path))
No such file or directory: 'c:\regions\new_zealand\tax_data.txt'

It’s readable, and if you have any issues with it, you can copy and paste it into Python to see what it actually looks like.

This is ONLY a problem with backslash path separators. Fortunately, you can usually use forward slashes instead, and all will be well.

It does for me:

>>> with open("/etc/example/notfound") as f: pass
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
FileNotFoundError: [Errno 2] No such file or directory: '/etc/example/notfound'

That’s the repr for that string. That’s exactly what you’re seeing.

I showed you the repr for that string, and you can see that it’s exactly what you’re getting in the error message.

You also used forward slashes. My issue is when backslashes are used. Oh well - I’ll close. Learned some good info. Thanks.

It is up to the application code to present messages to the user that are meaningful to the user.

In this case you would need to catch that exception and print the path without using repr based in the information in the exception args.

1 Like

Well, yes - because forward slashes are the path separator on Linux. The repr of the string with forward slashes in it is identical to its actual contents (assuming nothing else needs to be escaped); the repr of the string with backslashes is not (because the backslashes need to be escaped). But the repr is still used either way.

Incidentally, forward slashes work perfectly well for Windows paths - they’ll get translated at some point, I believe internally within the Windows API (since I’ve also seen advice to use forward slashes on Windows in C++ programs). Or, since you are already using Pathlib, you can compose the path out of each part separately: Path('C:') / 'Users' / 'steven' / 'Python' / 'test.txt'.