如何解决使用 Python 更快地获取 Windows 文件的所有者
长话短说:我正在制作一个数据库,其中包含我们公司曾经做过的所有报价。照顾特定的文件扩展名:*.prc 我要检索的信息之一是文件的所有者。 我正在使用以下代码(仅显示其中的一部分):
import os,time,win32security,subprocess
from threading import Thread
from time import time
def GET_THE_OWNER(FILENAME):
open (FILENAME,"r").close ()
sd = win32security.GetFileSecurity (FILENAME,win32security.OWNER_Security_informatION)
owner_sid = sd.GetSecurityDescriptorOwner ()
name,domain,type = win32security.LookupAccountSid (None,owner_sid)
return name
starttime = time()
path = "C:/Users/cbabycv/Documents/Python/0. Quotations/Example"
for root,dirs,files in os.walk(path):
for file in files:
if (file.endswith(".prc")):
#getting data from the file information
Filename = os.path.join(root,file)
try:
Owner = GET_THE_OWNER(Filename)
except:
Owner = "Could not get the owner."
print(Owner)
endtime = time()
print (Owner)
print(endtime-starttime," sec")
这个过程很慢(尤其是当你必须阅读大约 100.000 个文件时)。我想知道是否有另一种方法可以使其更快? 请注意,我要求的是 Windows 操作系统而不是其他所有东西(在这种情况下我不能使用 os.stat() - 根本不适用于 Windows) 我尝试过这里描述的另一种方式:how to find the owner of a file or directory in python 由 Paal Pedersen 提供,但它比使用 windows Api 还要慢
我正在使用 os.walk() 来查找服务器上的文件。我没有文件的确切位置,它们可以在任何文件夹中(所以我只是查看所有文件夹/子文件夹中的每个文件,看看它是否是 *.prc 文件)。一个建议的多处理 - 非常感谢 :) 我会尝试优化整个代码,但我的问题仍然有效 - 是否有更快/更好的方法在 Windows 操作系统中找到文件的所有者?
@theCreator 建议使用powershell。已经试过了。这是大约。慢 14 倍...
import os,subprocess
from pathlib import Path
from time import time
starttime = time()
def GET_THE_OWNER(cmd):
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
completed = subprocess.run(["powershell.exe","-Command","Get-Acl ",cmd," | Select-Object Owner"],capture_output=True,startupinfo=startupinfo)
return completed
path = Path('C:/Users/cbabycv/Documents/Python/0. Quotations/Example')
for root,file)
Filename = "\"" + Filename +"\""
Owner = GET_THE_OWNER(Filename)
if Owner.returncode != 0:
print("An error occured: %s",Owner.stderr)
else:
print(Owner.stdout)
endtime = time()
print(endtime-starttime," sec")
解决方法
试试这个,它会返回一个目录和子目录中所有所有者的列表。
import subprocess
mydirPath = "C:\pathTo\SomeStuff\\"
name = subprocess.call(["C:\\WINDOWS\\system32\\WindowsPowerShell\\v1.0\\powershell.exe","Get-ChildItem "+ mydirPath +" -Force -Recurse | select @{Name=\"Owner\";Expression={(Get-ACL $_.Fullname).Owner}}"
,
在这种情况下通过分析器运行代码很有用:
> python3 -m cProfile -s cumtime owners.py
1.251999855041504 sec
163705 function calls (158824 primitive calls) in 1.263 seconds
Ordered by: cumulative time
ncalls tottime percall cumtime percall filename:lineno(function)
5/1 0.000 0.000 1.263 1.263 {built-in method builtins.exec}
1 0.019 0.019 1.263 1.263 owners.py:1(<module>)
4999 0.024 0.000 1.058 0.000 owners.py:6(GET_THE_OWNER)
4999 0.423 0.000 0.423 0.000 {built-in method win32security.LookupAccountSid}
4999 0.264 0.000 0.280 0.000 {built-in method io.open}
4999 0.262 0.000 0.262 0.000 {built-in method win32security.GetFileSecurity}
5778/938 0.011 0.000 0.130 0.000 os.py:280(walk)
...
这里有一些无法帮助,但可以帮助调用 LookupAccountSid 和 io.open。 SID 不会改变,毫无疑问,与文件列表相比,您需要使用的 SID 列表相当小。我实际上不确定您为什么要打开和关闭文件,但仅此一项就需要花费大量时间:
_owner_sid_cache = {}
def GET_THE_OWNER(FILENAME):
# open (FILENAME,"r").close ()
sd = win32security.GetFileSecurity (FILENAME,win32security.OWNER_SECURITY_INFORMATION)
owner_sid = sd.GetSecurityDescriptorOwner ()
if str(owner_sid) not in _owner_sid_cache:
name,_domain,_type = win32security.LookupAccountSid (None,owner_sid)
_owner_sid_cache[str(owner_sid)] = name
return _owner_sid_cache[str(owner_sid)]
在使用此版本的函数和将数据输出到文件而不是相对较慢的控制台之间,时间从 252 秒减少到 5 秒,在我本地机器上有 60,000 个文件的测试文件夹中。
>版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。