[英]Python Script takes very long time to run
我设法编写了一段代码(由网络上的多个来源组成,并适应我的需要),它应该执行以下操作:
该代码实际上有效(使用只有 9 封电子邮件的电子邮件文件夹进行测试)。 我的问题是运行时间。
该脚本的实际范围是在包含 32700 封电子邮件的文件夹中查找 2539 个值并保存附件。
我已经完成了 2 次运行,如下所示:
我想知道/学习,是否有办法使脚本更快,或者它是否因为写得不好等而变慢。
下面是我的代码:
from pathlib import Path
import win32com.client
import os
from datetime import datetime
import time
import openpyxl
#name of the folder created for output
output_dir = Path.cwd() / "Orders"
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
folder = outlook.Folders.Item("Shared Mailbox Name")
inbox = folder.Folders.Item("Inbox")
messages = inbox.Items
wb = openpyxl.load_workbook(r"C:\Users\TEST\Path-to-excel\FolderName\ExcelName.xlsx")
sheet = wb['Sheet1']
names=sheet['A']
for cellObj in names:
ordno = str(cellObj.value)
print(ordno)
for message in messages:
subject = message.Subject
body = message.body
attachments = message.Attachments
if str(subject)[:9] == ordno:
output_dir.mkdir(parents=True, exist_ok=True)
for attachment in attachments:
attachment.SaveAsFile(output_dir / str(attachment))
else:
pass
start = time()
print(f'Time taken to run: {time() - start} seconds')
我需要提一下,我是 Python 的新手,因此欢迎社区提供任何帮助,尤其是在澄清我做错了什么以及为什么做错之后。
我也读过一些类似的问题,但没有任何帮助,或者至少我不知道如何采用这些方法。
谢谢!
您的用例过于具体,任何人都无法重新创建,并且仅提供通用性能提示,但您的主要问题是“O x N”和同步处理的组合:目前您正在处理一个值,一次处理一条消息,其中包括用于获取电子邮件的磁盘 IO。
您当然可以通过从工作簿创建单个值列表来改进事情。 然后,您可以将此列表与处理池一起使用(请参阅 Python 文档)来一次阅读多封电子邮件。
但是如果您可以使用主题来查询邮件服务器,情况可能会更好。
如果您有后续问题,请将它们分解为任务的特定部分。
首先,而不是遍历文件夹中的所有项目:
for message in messages:
subject = message.Subject
然后检查一个主题是从指定的字符串开始还是包含这样的字符串:
if str(subject)[:9] == ordno:
相反,您需要使用 Items 类的Find
/ FindNext
或 Restrict methods of the
,您可以在其中获取与您的搜索条件相对应的项目集合。 在以下文章中阅读有关这些方法的更多信息:
例如,您可以对集合使用以下限制(取自 VBA 示例):
criteria = "@SQL=" & Chr(34) & "urn:schemas:httpmail:subject" & Chr(34) & " ci_phrasematch 'question'"
有关详细信息,请参阅使用字符串比较过滤项目。
此外,您可能会发现Application
类的AdvancedSearch
方法很有帮助。 在 Outlook 中使用AdvancedSearch
方法的主要好处是:
AdvancedSearch
方法会在后台自动运行它。Restrict
和Find
/ FindNext
方法可以应用于特定的Items
集合(请参阅 Outlook 中Folder
类的Items
属性)。Store
类的IsInstantSearchEnabled
属性)。Search
类的Stop
方法随时停止搜索过程。有关详细信息,请参阅Outlook 中的高级搜索以编程方式:C#、VB.NET 。
在我看来,您的程序的主要问题是当您只需要遍历邮件并检查它们的主题是否在值列表中时,您有两个嵌套循环(一个在值上,一个在邮件上)。
首先,您需要使用以下内容构建价值列表:
ordno_values = [str(cellObj.value) for cellObj in names]
然后,在您的邮件循环中,您只需要将条件调整为:
if str(subject)[:9] in ordno_values:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.