Update: I revised this to include the Mac way of finding the user’s documents directory. Perhaps the Python standard library should include a way to get at the best path for storing documents.

For Windows

Yuck. Coming within 10 feet of win32 programming, you can really appreciate the need for .NET and a sane API.

For anyone needing to find the user’s “My Documents” folder on Windows with Python, here is one way that I’ve found to work based on this MSDN article. (As awful as the API is, I will say that MSDN is a great resource!)

from win32com.shell import shell
df = shell.SHGetDesktopFolder()
pidl = df.ParseDisplayName(0, None,
    "::{450d8fba-ad25-11d0-98a8-0800361b1103}")[1]
mydocs = shell.SHGetPathFromIDList(pidl)

I really wanted to use shell.SHGetFolderPath but I couldn’t get a combination that works for retrieving “My Documents”. In order to get My Documents from there, you need a PyHandle for the user, and I got the method above working before I found my handle… You can get “My Pictures” easily from shell.SHGetFolderPath, however.

from win32com import shell, shellcon
mypict = shell.SHGetFolderPath(0, shellcon.CSIDL_MYPICTURES, 0, 0)

I’m sure that if you do win32 programming all the time, you get used to this stuff. Knowing that doesn’t make me feel less sorry for the folks that are doing win32 programming.

For The Mac

The Mac (Carbon) way of doing this is similar to the SHGetFolderPath call on Windows. Both of these APIs make more sense than the one I went with (ParseDisplayName with that lovely GUID).

from Carbon import Folder, Folders
folderref = Folder.FSFindFolder(Folders.kUserDomain,
    Folders.kDocumentsFolderType, False)
docs = folderref.as_pathname()

9 Responses to “Finding a user’s Documents folder on Windows and Mac”
  1. Kent Johnson says:

    Did you try the method in Tim Golden’s winshell.py? It is a bit more straightforward.

    http://tgolden.sc.sabren.com/python/winshell.html

  2. tazzzzz says:

    I hadn’t seen that, oddly enough. That certainly does have an API that is more pleasant.

    I’d imagine that the author would be happy to fix this, but I noticed that there’s no license listed for it… which essentially renders it unusable.

    Thanks for the link!

  3. Ronald Oussoren says:

    An alternative on the mac using PyObjC:

    from Foundation import *
    docs = NSSearchPathForDirectoriesInDomains(
    NSDocumentDirectory, NSUserDomainMask, True)[0]

  4. tazzzzz says:

    Thank you! I was certain there was a Cocoa way to do it, and I’d rather do it the Cocoa way…

  5. Kent Johnson says:

    You’re right about the lack of license for winshell.py. I’ve just emailed Tim Golden asking if he would clarify this.

  6. Tim Keating says:

    As an alternative, on Windows — and I know, this is just crazy talk from a Linux programmer — you could do os.path.join(os.getenv(’USERPROFILE’), ‘My Documents’).

  7. tazzzzz says:

    Microsoft strongly recommends using the style that I pointed to, for a couple of good reasons. One is that “My Documents” is apparently some kind of virtual folder and is not guaranteed to be where you think it is. The other is the “My Documents” is English… the folder itself isn’t guaranteed to be called “My Documents”.

  8. Eric H. Jung says:

    It’s not that “My Documents” is a virtual folder, it’s that each user can change the location of “My Documents” to wherever he likes. Assuming it’s under the user’s profile is a big mistake. It can very easily be under the root or /temp or anything else…

  9. Irwin Oppenheim says:

    This bit of code worked for me:

    from win32com.shell import shell, shellcon
    mydocuments = shell.SHGetFolderPath(0, shellcon.CSIDL_PERSONAL, 0, 0)

    I found a whole list of constants here:
    http://www.theutilityfactory.com/online_help/index.html?hidd_special_folders.htm

    Best,
    Irwin

Leave a Reply