Posting this since it's a likely cause of problems like this, if not necessarily in this specific case. Desktop (along with most other user folders) is a pseudo-magic folder, and you can't rely on it always being found at C:\Users\USERNAME\Desktop. In particular, just because you see a file on your desktop doesn't mean it's actually there. It could be in the All Users Desktop folder, and either of those could be redirected by the Windows Library folder redirection magic.
If you want to get the correct path to the user's desktop dynamically, you can use the pywin32 extension to do so:
from win32com.shell import shell, shellcon
shell.SHGetFolderPath(0, shellcon.CSIDL_MYPICTURES, None, 0)
(hat tip to this answer), or to get the common Desktop folder for all users:
import win32com.client
objShell = win32com.client.Dispatch("WScript.Shell")
allUserDocs = objShell.SpecialFolders("AllUsersDesktop")
(hat tip to this answer).
Both approaches above might be replaceable on Vista and higher with code that calls SHGetKnownFolderPath (either with pywin32 if it supports it, or directly through a ctypes wrapper) using FOLDERID_Desktop and FOLDERID_PublicDesktop for the user specific and commonly shared Desktop folders.
open(), check if the file exists os.path.exists()open) and wasted time on thestatcheck, whenopenitself implicitly checks existence. Correct solution is EAFP: callopen, catchOSError(or subclasses thereof in modern Python, e.g.FileNotFoundErrorin this case) if you can handle the error.os.path.existsis fine for interactive interpreter debugging, but not production code.newline=''to disable line ending translation, so thecsvmodule can handle line ending translation correctly per the CSV dialect in use. Opening in binary mode was how you handled this in Python 2, because Python 2 wasn'tunicodefriendly, so binary mode avoided decoding and newline translation at once.