Python 如何以编程方式确定Dropbox文件夹位置?

Python 如何以编程方式确定Dropbox文件夹位置?,python,directory,dropbox,Python,Directory,Dropbox,我有一个脚本,打算由多台计算机上的多个用户运行,但他们并没有在各自的主目录中都有Dropbox文件夹。我不想在脚本中硬编码路径。我更愿意通过编程找出路径 欢迎任何建议 编辑: 我没有在脚本中使用Dropbox API,脚本只是读取用户之间共享的特定Dropbox文件夹中的文件。我唯一需要的是Dropbox文件夹的路径,因为我当然已经知道Dropbox文件结构中的相对路径 编辑: 如果重要的话,我使用的是Windows 7。您可以使用os.walk搜索文件系统。Dropbox文件夹可能位于用户的主

我有一个脚本,打算由多台计算机上的多个用户运行,但他们并没有在各自的主目录中都有Dropbox文件夹。我不想在脚本中硬编码路径。我更愿意通过编程找出路径

欢迎任何建议

编辑: 我没有在脚本中使用Dropbox API,脚本只是读取用户之间共享的特定Dropbox文件夹中的文件。我唯一需要的是Dropbox文件夹的路径,因为我当然已经知道Dropbox文件结构中的相对路径

编辑:
如果重要的话,我使用的是Windows 7。

您可以使用
os.walk
搜索文件系统。Dropbox文件夹可能位于用户的主目录中,因此为了节省时间,您可以将搜索限制在该目录中。例如:

import os
dropbox_folder = None

for dirname, dirnames, filenames in os.walk(os.path.expanduser('~')):
    for subdirname in dirnames:
        if(subdirname == 'Dropbox'):
            dropbox_folder = os.path.join(dirname, subdirname)
            break
    if dropbox_folder:
        break

# dropbox_folder now contains the full path to the Dropbox folder, or
# None if the folder wasn't found


或者,您可以提示用户输入Dropbox文件夹位置,或者通过配置文件对其进行配置。

一个选项是您可以搜索
.Dropbox.cache
目录,该目录(至少在Mac和Linux上)是Dropbox目录中的隐藏文件夹

我相当确定Dropbox将其首选项存储在加密的
.dbx
容器中,因此使用Dropbox使用的相同方法提取它并不简单。

我找到了答案。将
s
设置为等于
~\AppData\Roaming\Dropbox\host.db
中的第二行,然后用base64对其进行解码,即可得到路径

def _get_appdata_path():
    import ctypes
    from ctypes import wintypes, windll
    CSIDL_APPDATA = 26
    _SHGetFolderPath = windll.shell32.SHGetFolderPathW
    _SHGetFolderPath.argtypes = [wintypes.HWND,
                                 ctypes.c_int,
                                 wintypes.HANDLE,
                                 wintypes.DWORD,
                                 wintypes.LPCWSTR]
    path_buf = wintypes.create_unicode_buffer(wintypes.MAX_PATH)
    result = _SHGetFolderPath(0, CSIDL_APPDATA, 0, 0, path_buf)
    return path_buf.value

def dropbox_home():
    from platform import system
    import base64
    import os.path
    _system = system()
    if _system in ('Windows', 'cli'):
        host_db_path = os.path.join(_get_appdata_path(),
                                    'Dropbox',
                                    'host.db')
    elif _system in ('Linux', 'Darwin'):
        host_db_path = os.path.expanduser('~'
                                          '/.dropbox'
                                          '/host.db')
    else:
        raise RuntimeError('Unknown system={}'
                           .format(_system))
    if not os.path.exists(host_db_path):
        raise RuntimeError("Config path={} doesn't exists"
                           .format(host_db_path))
    with open(host_db_path, 'r') as f:
        data = f.read().split()

    return base64.b64decode(data[1])

这应该在Win7上工作。使用
getEnvironmentVariable(“APPDATA”)
而不是
os.getenv(“APPDATA”)
支持Unicode文件路径——请参阅题为的问题

导入base64
导入ctypes
导入操作系统
def getEnvironmentVariable(名称):
“”“读取windows本机unicode环境变量”“”
#(可以在Python 3中使用os.environ dict)
name=unicode(name)#确保字符串参数为unicode
n=ctypes.windell.kernel32.GetEnvironmentVariables(名称,无,0)
如果不是n:
一无所获
其他:
buf=ctypes。创建\u unicode\u缓冲区(u'\0'*n)
ctypes.windell.kernel32.GetEnvironmentVariables(名称,buf,n)
返回基本单位值
def getDropboxRoot():
#从Dropbox的sqlite host.db数据库中查找其根监视文件夹的路径。
#Dropbox将其数据库存储在当前登录用户的%APPDATA%路径下。
#如果您在同一登录名下安装了多个dropbox实例,则只会找到第一个实例。
#Dropbox将其数据库存储在当前登录用户的%APPDATA%路径下。
#通常为“C:\Documents and Settings\\Application Data”
sConfigFile=os.path.join(getEnvironmentVariable(“APPDATA”),
“Dropbox”、“host.db”)
#如果找不到或无法使用数据库文件,则返回空字符串。
如果操作系统路径不存在(sConfigFile):
一无所获
#Dropbox Watch文件夹位置以base64编码为host.db文件的最后一行。
打开(sConfigFile)作为dbxfile时:
对于dbxfile中的sLine:
通过
#解码最后一行,到dropbox watch文件夹的路径,不带尾随斜杠。
返回base64.b64解码(sLine)
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
打印getDropboxRoot()
这一基于作者建议的改编对我在Ubuntu上很有效:

os.path.expanduser('~/Dropbox')
要实际设置工作目录,请执行以下操作:

os.chdir(os.path.expanduser('~/Dropbox'))

Dropbox帮助中心对此有一个答案-

简短版本: 使用
~/.dropbox/info.json
%APPDATA%\dropbox\info.json

长版本: 通过以下方式访问有效的
%APPDATA%
%LOCALAPPDATA%
位置:

import os
from pathlib import Path
import json

try:
    json_path = (Path(os.getenv('LOCALAPPDATA'))/'Dropbox'/'info.json').resolve()
except FileNotFoundError:
    json_path = (Path(os.getenv('APPDATA'))/'Dropbox'/'info.json').resolve()

with open(str(json_path)) as f:
    j = json.load(f)

personal_dbox_path = Path(j['personal']['path'])
business_dbox_path = Path(j['business']['path'])
注:答案适用于Dropbox v2.8及更高版本

窗口

jq -r ".personal.path" < %APPDATA%\Dropbox\info.json
jq -r ".personal.path" < ~/.dropbox/info.json 

类似于使用发行版的软件包管理器安装Windows。

注意:需要Dropbox>=2.8

。它位于以下两个位置之一:

%APPDATA%\Dropbox\info.json
%LOCALAPPDATA%\Dropbox\info.json
我可以通过
os.environ['APPDATA']
访问Python中的
%APPDATA%
环境变量,但是我会同时检查该变量和
os.environ['LOCALAPPDATA']
。然后我将JSON转换成一个字典,并读取相应Dropbox(业务或个人)下的
'path'

从下面的代码调用
get\u dropbox\u location()
将返回业务dropbox的文件路径,而
get\u dropbox\u location('personal')
将返回个人dropbox的文件路径

import os
import json

def get_dropbox_location(account_type='business'):
    """
    Returns a string of the filepath of the Dropbox for this user

    :param account_type: str, 'business' or 'personal'
    """
    info_path = _get_dropbox_info_path()
    info_dict = _get_dictionary_from_path_to_json(info_path)
    return _get_dropbox_path_from_dictionary(info_dict, account_type)

def _get_dropbox_info_path():
    """
    Returns filepath of Dropbox file info.json
    """
    path = _create_dropox_info_path('APPDATA')
    if path:
        return path
    return _create_dropox_info_path('LOCALAPPDATA')

def _create_dropox_info_path(appdata_str):
    r"""
    Looks up the environment variable given by appdata_str and combines with \Dropbox\info.json

    Then checks if the info.json exists at that path, and if so returns the filepath, otherwise
    returns False
    """
    path = os.path.join(os.environ[appdata_str], r'Dropbox\info.json')
    if os.path.exists(path):
        return path
    return False

def _get_dictionary_from_path_to_json(info_path):
    """
    Loads a json file and returns as a dictionary
    """
    with open(info_path, 'r') as f:
        text = f.read()

    return json.loads(text)

def _get_dropbox_path_from_dictionary(info_dict, account_type):
    """
    Returns the 'path' value under the account_type dictionary within the main dictionary
    """
    return info_dict[account_type]['path']

这是一个纯Python解决方案,与使用
info.json的其他解决方案不同,脚本应该做什么?您正在使用吗?我确实实现了这一点,但后来我发现一些用户将他们的Dropbox文件夹放在主目录之外……然后只需搜索整个文件系统即可。它只会在找到名为Dropbox的文件夹之前进行搜索。我仍然认为最好的解决方案是提示用户。这将找到用户的Dropbox应用程序文件夹,但这不一定是Dropbox实际存储用户数据文件的位置(有默认值,但它是用户定义的)。该信息存储在该目录下的
host.db
文件中。要在Windows上查找host.db,请执行以下操作:
host\u db\u path=os.path.join(winpath.get\u appdata(),'Dropbox','host.db')
而不是
winpath
。在Linux上,OSX:
host\u db\u path=os.path.expanduser('~/.dropbox/host.db')
raiseruntimeerror(“配置路径={}不存在”)。格式(p))
给出
NameError:global name“p”没有定义
。我认为应该是
raiseruntimeerror(“配置路径={}不存在”。format(host\u db\u路径))
dropbox\u主页()函数在Android上不起作用。dropbox host.db文件在最新版本中不再存在..Grr..正在寻找新的解决方案。仅当dropbox实际安装在那里时。
import os
import json

def get_dropbox_location(account_type='business'):
    """
    Returns a string of the filepath of the Dropbox for this user

    :param account_type: str, 'business' or 'personal'
    """
    info_path = _get_dropbox_info_path()
    info_dict = _get_dictionary_from_path_to_json(info_path)
    return _get_dropbox_path_from_dictionary(info_dict, account_type)

def _get_dropbox_info_path():
    """
    Returns filepath of Dropbox file info.json
    """
    path = _create_dropox_info_path('APPDATA')
    if path:
        return path
    return _create_dropox_info_path('LOCALAPPDATA')

def _create_dropox_info_path(appdata_str):
    r"""
    Looks up the environment variable given by appdata_str and combines with \Dropbox\info.json

    Then checks if the info.json exists at that path, and if so returns the filepath, otherwise
    returns False
    """
    path = os.path.join(os.environ[appdata_str], r'Dropbox\info.json')
    if os.path.exists(path):
        return path
    return False

def _get_dictionary_from_path_to_json(info_path):
    """
    Loads a json file and returns as a dictionary
    """
    with open(info_path, 'r') as f:
        text = f.read()

    return json.loads(text)

def _get_dropbox_path_from_dictionary(info_dict, account_type):
    """
    Returns the 'path' value under the account_type dictionary within the main dictionary
    """
    return info_dict[account_type]['path']