You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Python中跨Windows、macOS、Linux获取用户文档文件夹(含自定义路径)

跨平台获取用户文档文件夹(支持自定义路径)

好问题!跨平台获取用户的文档目录确实得兼顾默认路径和用户自定义的情况,我来给你梳理下macOS和Linux的实现方案,再整合Windows的逻辑,凑个完整的跨平台解决方案~

Windows 实现(补充你已有的方案)

Windows下要获取用户修改后的文档路径,最靠谱的是调用系统原生API,而不是硬编码默认路径。这里给两种常用实现:

  • pywin32库(更简洁):
from win32com.client import Dispatch

shell = Dispatch("WScript.Shell")
documents_path = shell.SpecialFolders("MyDocuments")
  • 依赖标准库ctypes(无需额外安装):
import ctypes
from ctypes import wintypes

CSIDL_PERSONAL = 5  # 文档文件夹的系统标识
SHGFP_TYPE_CURRENT = 0  # 获取当前实际路径(而非默认)

buf = wintypes.LPWSTR()
ctypes.windll.shell32.SHGetFolderPathW(None, CSIDL_PERSONAL, None, SHGFP_TYPE_CURRENT, ctypes.byref(buf))
documents_path = buf.value
ctypes.windll.kernel32.LocalFree(buf)

这两种方式都能准确返回用户手动修改后的文档路径。

macOS 实现

macOS下用户修改文档位置后,不能直接拼接/Users/<user>/Documents,得调用系统API来获取:

方法1:用pyobjc调用AppKit框架(推荐)

先安装依赖:pip install pyobjc

from AppKit import NSWorkspace

def get_macos_documents_path():
    # 调用系统API获取文档目录URL
    docs_url = NSWorkspace.sharedWorkspace().URLForDirectory_inDomain_appropriateForURL_create_error_(
        9,  # NSDocumentDirectory 对应的枚举值
        1,  # NSUserDomainMask:当前用户域
        None,
        False,
        None
    )
    return docs_url.path() if docs_url else None

方法2:用osascript调用AppleScript(无需额外依赖)

如果不想安装pyobjc,可以通过执行AppleScript来获取:

import subprocess

def get_macos_documents_path():
    result = subprocess.run(
        ['osascript', '-e', 'tell application "Finder" to get POSIX path of (path to documents folder)'],
        capture_output=True,
        text=True
    )
    if result.returncode == 0:
        return result.stdout.strip()
    return None

Linux 实现

Linux遵循XDG规范,用户修改文档路径后会存在~/.config/user-dirs.dirs文件中,或者可以用xdg-user-dir命令直接获取:

方法1:调用xdg-user-dir命令(推荐)

大部分主流发行版都预装了这个工具,直接调用即可:

import subprocess

def get_linux_documents_path():
    result = subprocess.run(
        ['xdg-user-dir', 'DOCUMENTS'],
        capture_output=True,
        text=True
    )
    if result.returncode == 0:
        return result.stdout.strip()
    # 命令失败时 fallback到默认路径
    import os
    return os.path.expanduser('~/Documents')

方法2:读取user-dirs.dirs文件解析

如果系统没有xdg-user-dir,可以直接读取配置文件:

import os

def get_linux_documents_path():
    user_dirs_file = os.path.expanduser('~/.config/user-dirs.dirs')
    if os.path.exists(user_dirs_file):
        with open(user_dirs_file, 'r') as f:
            for line in f:
                line = line.strip()
                if line.startswith('XDG_DOCUMENTS_DIR='):
                    # 去掉引号并替换$HOME为实际用户目录
                    path = line.split('=')[1].strip('"')
                    return os.path.expanduser(path)
    # fallback到默认路径
    return os.path.expanduser('~/Documents')

跨平台整合函数

把上面的逻辑整合到一个函数里,自动适配不同系统:

import os
import sys

def get_user_documents_path():
    if sys.platform.startswith('win32'):
        # Windows分支
        try:
            from win32com.client import Dispatch
            shell = Dispatch("WScript.Shell")
            return shell.SpecialFolders("MyDocuments")
        except ImportError:
            # 用ctypes作为备选
            import ctypes
            from ctypes import wintypes
            CSIDL_PERSONAL = 5
            SHGFP_TYPE_CURRENT = 0
            buf = wintypes.LPWSTR()
            ctypes.windll.shell32.SHGetFolderPathW(None, CSIDL_PERSONAL, None, SHGFP_TYPE_CURRENT, ctypes.byref(buf))
            path = buf.value
            ctypes.windll.kernel32.LocalFree(buf)
            return path
    elif sys.platform.startswith('darwin'):
        # macOS分支
        try:
            from AppKit import NSWorkspace
            docs_url = NSWorkspace.sharedWorkspace().URLForDirectory_inDomain_appropriateForURL_create_error_(
                9, 1, None, False, None
            )
            return docs_url.path() if docs_url else os.path.expanduser('~/Documents')
        except ImportError:
            # 用osascript作为备选
            import subprocess
            result = subprocess.run(
                ['osascript', '-e', 'tell application "Finder" to get POSIX path of (path to documents folder)'],
                capture_output=True, text=True
            )
            if result.returncode == 0:
                return result.stdout.strip()
            return os.path.expanduser('~/Documents')
    elif sys.platform.startswith('linux'):
        # Linux分支
        try:
            import subprocess
            result = subprocess.run(['xdg-user-dir', 'DOCUMENTS'], capture_output=True, text=True)
            if result.returncode == 0:
                return result.stdout.strip()
        except (subprocess.CalledProcessError, FileNotFoundError):
            pass
        # 读取配置文件作为备选
        user_dirs_file = os.path.expanduser('~/.config/user-dirs.dirs')
        if os.path.exists(user_dirs_file):
            with open(user_dirs_file, 'r') as f:
                for line in f:
                    line = line.strip()
                    if line.startswith('XDG_DOCUMENTS_DIR='):
                        path = line.split('=')[1].strip('"')
                        return os.path.expanduser(path)
        return os.path.expanduser('~/Documents')
    else:
        # 未知平台返回默认路径
        return os.path.expanduser('~/Documents')

# 测试调用
print(get_user_documents_path())

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

火山引擎 最新活动