如何在 Python 中声明和调用基于其他分层变量的动态变量?

How can I declare and call a dynamic variable based on other hierarchical variables in Python?

我正在尝试编写一个抓取程序,当我指定要从中下载的文件夹路径时,它将从 outlook 帐户下载附件。我有工作代码,但文件夹位置硬编码如下:-

import win32com.client

outlook = win32com.client.Dispatch("Outlook.Application")
namespace = outlook.GetNamespace("MAPI")
root_folder = namespace.Folders.Item('Personal') #Inbox of interest
subfolder = root_folder.Folders['Inbox'].Folders['Holidays'].Folders['2009'].Folders['June'] #I have  Holidays,2009 and June folders in that hierarchical order in the  mailbox called Personal
Messages = subfolder.Items

使用代码,我可以根据其他预设参数从收件箱中抓取电子邮件和附件。

但是,我对动态执行此操作很感兴趣,这样根据嵌套文件夹的数量,我将能够构建 子文件夹 变量,如以上代码。我已经使用以下代码进行了尝试。

import win32com.client

outlook = win32com.client.Dispatch("Outlook.Application")
namespace = outlook.GetNamespace("MAPI")            

root_mailbox  = str(input("Please Enter the Root folder name for the mailbox to scrape from:")) #Mailbox  to download from i.e. may be like "Personal" above.
if (root_mailbox == ""):
    print("You cannot leave this empty. Please insert the root folder name.")
else:
    
    root_folder = namespace.Folders.Item(root_mailbox) 
    sub_folders_num = int(input('How  many subfolders  are to be iterated on in the mailbox. Remember this has to be a number.')) #Specify the number of folders

    foldernames = [] #List to append to names values
    for i in range(1,sub_folders_num+1): 
        i = input("Input folder name(s) starting  with the one closest to the root folder") 
        foldernames.append(i)      
                

subfolder = root_folder.Folders[foldernames[0]].Folders[foldernames[1]].Folders[foldernames[2]] # Subfolder path but still "manually" specified 
Messages = subfolder.Items

subfolder 变量将有效,但该过程仍然是手动的。我怎样才能根据 sub_folders_num 和使用循环中捕获的列表值构建的子文件夹路径动态指定“文件夹”?这将有助于创建一个更动态的抓取工具,我可以从任何收件箱文件夹路径下载 emails/attachments。

您可以将此作为 reduction 而不是 foldernames 使用 getattr 来动态获取下一个属性。

from functools import reduce


subfolder = reduce(lambda x, y: getattr(x, x.Folders[y]), foldernames, root_folder)

或者,一种不太优雅但更易于调试的非功能性方法:

subfolder = root_folder
for folder_name in foldernames:
    subfolder = subfolder.Folders[folder_name]

最终结果应该与reduce方法相同。

看来您需要递归地遍历 Outlook 中的所有文件夹。这是一个示例 VBA 宏,因此您可能会看到 属性 的序列和完成工作的方法调用:

private void EnumerateFoldersInDefaultStore()
{
    Outlook.Folder root =
        Application.Session.
        DefaultStore.GetRootFolder() as Outlook.Folder;
    EnumerateFolders(root);
}

// Uses recursion to enumerate Outlook subfolders.
private void EnumerateFolders(Outlook.Folder folder)
{
    Outlook.Folders childFolders = folder.Folders;
    if (childFolders.Count > 0)
    {
        foreach (Outlook.Folder childFolder in childFolders)
        {
            // Write the folder path.
            Debug.WriteLine(childFolder.FolderPath);
            // Call EnumerateFolders using childFolder.
            EnumerateFolders(childFolder);
        }
    }
}