【问题标题】:Getting the owner of the file for Windows with Python faster使用 Python 更快地获取 Windows 文件的所有者
【发布时间】:2021-05-20 17:53:21
【问题描述】:

长话短说:我正在建立一个数据库,其中包含我们公司曾经做过的所有报价。照顾特定的文件扩展名:*.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, 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)
            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")

【问题讨论】:

标签: python windows file owner


【解决方案1】:

在这种情况下,通过分析器运行代码很有用:

> 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 个文件的测试文件夹上。

【讨论】:

  • 感谢您的宝贵时间!实际上,根据您的建议,我将时间缩短了一半 :) 对于您对打开和关闭文件的疑惑……您知道,我是 python 和编程的新手,还在学习,还有很多要学习的东西。但总有一天我会在那里!周末愉快。
【解决方案2】:

试试这个,它会返回一个目录和子目录中所有所有者的列表。

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}}" 

【讨论】:

  • 1.执行需要 5 到 6 倍的时间 2. 它不工作 :) 结果我得到一个窗口和一个整数。
猜你喜欢
  • 1970-01-01
  • 2015-10-22
  • 1970-01-01
  • 2016-03-19
  • 2018-08-18
  • 2017-05-07
  • 2011-01-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多