如何在 Windows 上以提升的权限运行 python 脚本
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19672352/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to run python script with elevated privilege on windows
提问by sundar_ima
I am writing a pyqt application which require to execute admin task. I would prefer to start my script with elevate privilege. I am aware that this question is asked many times in SO or in other forum. But the solution people are suggesting is to have a look at this SO question Request UAC elevation from within a Python script?
我正在编写一个需要执行管理任务的 pyqt 应用程序。我更愿意以提升权限启动我的脚本。我知道这个问题在 SO 或其他论坛中被问过很多次。但是人们建议的解决方案是看一下这个问题, 从 Python 脚本中请求 UAC 提升?
However, I am unable to execute the sample code given in the link. I have put this code on top of the main file and tried to execute it.
但是,我无法执行链接中给出的示例代码。我已将此代码放在主文件的顶部并尝试执行它。
import os
import sys
import win32com.shell.shell as shell
ASADMIN = 'asadmin'
if sys.argv[-1] != ASADMIN:
script = os.path.abspath(sys.argv[0])
params = ' '.join([script] + sys.argv[1:] + [ASADMIN])
shell.ShellExecuteEx(lpVerb='runas', lpFile=sys.executable, lpParameters=params)
sys.exit(0)
print "I am root now."
It actually ask permission to elevate but print line never get executed. Somebody can help me to run the above code successfully. Thanks in advance.
它实际上要求提升权限,但打印线永远不会被执行。有人可以帮我成功运行上面的代码。提前致谢。
采纳答案by sundar_ima
Thank you all for your reply. I have got my script working with the module/ script written by Preston Landers way back in 2010. After two days of browsing the internet I could find the script as it was was deeply hidden in pywin32 mailing list. With this script it is easier to check if the user is admin and if not then ask for UAC/ admin right. It does provide output in separate windows to find out what the code is doing. Example on how to use the code also included in the script. For the benefit of all who all are looking for UAC on windows have a look at this code. I hope it helps someone looking for same solution. It can be used something like this from your main script:-
谢谢大家的回复。早在 2010 年,我就让我的脚本与 Preston Landers 编写的模块/脚本一起工作。浏览互联网两天后,我可以找到脚本,因为它深深地隐藏在 pywin32 邮件列表中。使用此脚本可以更轻松地检查用户是否为管理员,如果不是,则请求 UAC/管理员权限。它确实在单独的窗口中提供输出以找出代码在做什么。关于如何使用也包含在脚本中的代码的示例。为了所有在 Windows 上寻找 UAC 的人的利益,请查看此代码。我希望它可以帮助寻找相同解决方案的人。它可以从你的主脚本中使用这样的东西:-
import admin
if not admin.isUserAdmin():
admin.runAsAdmin()
The actual code is:-
实际代码是:-
#!/usr/bin/env python
# -*- coding: utf-8; mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vim: fileencoding=utf-8 tabstop=4 expandtab shiftwidth=4
# (C) COPYRIGHT ? Preston Landers 2010
# Released under the same license as Python 2.6.5
import sys, os, traceback, types
def isUserAdmin():
if os.name == 'nt':
import ctypes
# WARNING: requires Windows XP SP2 or higher!
try:
return ctypes.windll.shell32.IsUserAnAdmin()
except:
traceback.print_exc()
print "Admin check failed, assuming not an admin."
return False
elif os.name == 'posix':
# Check for root on Posix
return os.getuid() == 0
else:
raise RuntimeError, "Unsupported operating system for this module: %s" % (os.name,)
def runAsAdmin(cmdLine=None, wait=True):
if os.name != 'nt':
raise RuntimeError, "This function is only implemented on Windows."
import win32api, win32con, win32event, win32process
from win32com.shell.shell import ShellExecuteEx
from win32com.shell import shellcon
python_exe = sys.executable
if cmdLine is None:
cmdLine = [python_exe] + sys.argv
elif type(cmdLine) not in (types.TupleType,types.ListType):
raise ValueError, "cmdLine is not a sequence."
cmd = '"%s"' % (cmdLine[0],)
# XXX TODO: isn't there a function or something we can call to massage command line params?
params = " ".join(['"%s"' % (x,) for x in cmdLine[1:]])
cmdDir = ''
showCmd = win32con.SW_SHOWNORMAL
#showCmd = win32con.SW_HIDE
lpVerb = 'runas' # causes UAC elevation prompt.
# print "Running", cmd, params
# ShellExecute() doesn't seem to allow us to fetch the PID or handle
# of the process, so we can't get anything useful from it. Therefore
# the more complex ShellExecuteEx() must be used.
# procHandle = win32api.ShellExecute(0, lpVerb, cmd, params, cmdDir, showCmd)
procInfo = ShellExecuteEx(nShow=showCmd,
fMask=shellcon.SEE_MASK_NOCLOSEPROCESS,
lpVerb=lpVerb,
lpFile=cmd,
lpParameters=params)
if wait:
procHandle = procInfo['hProcess']
obj = win32event.WaitForSingleObject(procHandle, win32event.INFINITE)
rc = win32process.GetExitCodeProcess(procHandle)
#print "Process handle %s returned code %s" % (procHandle, rc)
else:
rc = None
return rc
def test():
rc = 0
if not isUserAdmin():
print "You're not an admin.", os.getpid(), "params: ", sys.argv
#rc = runAsAdmin(["c:\Windows\notepad.exe"])
rc = runAsAdmin()
else:
print "You are an admin!", os.getpid(), "params: ", sys.argv
rc = 0
x = raw_input('Press Enter to exit.')
return rc
if __name__ == "__main__":
sys.exit(test())
回答by andrew cooke
in comments to the answer you took the code fromsomeone says ShellExecuteEx doesn't post its STDOUT back to the originating shell. so you will not see "I am root now", even though the code is probably working fine.
在对答案的评论中,您从某人那里获取了代码,说ShellExecuteEx 不会将其 STDOUT 发布回原始 shell。所以你不会看到“我现在是 root”,即使代码可能工作正常。
instead of printing something, try writing to a file:
不要打印一些东西,而是尝试写入文件:
import os
import sys
import win32com.shell.shell as shell
ASADMIN = 'asadmin'
if sys.argv[-1] != ASADMIN:
script = os.path.abspath(sys.argv[0])
params = ' '.join([script] + sys.argv[1:] + [ASADMIN])
shell.ShellExecuteEx(lpVerb='runas', lpFile=sys.executable, lpParameters=params)
sys.exit(0)
with open("somefilename.txt", "w") as out:
print >> out, "i am root"
and then look in the file.
然后查看文件。
回答by Florent B.
Here is a solution with an stdout redirection:
这是一个带有标准输出重定向的解决方案:
def elevate():
import ctypes, win32com.shell.shell, win32event, win32process
outpath = r'%s\%s.out' % (os.environ["TEMP"], os.path.basename(__file__))
if ctypes.windll.shell32.IsUserAnAdmin():
if os.path.isfile(outpath):
sys.stderr = sys.stdout = open(outpath, 'w', 0)
return
with open(outpath, 'w+', 0) as outfile:
hProc = win32com.shell.shell.ShellExecuteEx(lpFile=sys.executable, \
lpVerb='runas', lpParameters=' '.join(sys.argv), fMask=64, nShow=0)['hProcess']
while True:
hr = win32event.WaitForSingleObject(hProc, 40)
while True:
line = outfile.readline()
if not line: break
sys.stdout.write(line)
if hr != 0x102: break
os.remove(outpath)
sys.stderr = ''
sys.exit(win32process.GetExitCodeProcess(hProc))
if __name__ == '__main__':
elevate()
main()
回答by delphifirst
I found a very easy solution to this problem.
我找到了一个非常简单的解决这个问题的方法。
- Create a shortcut for
python.exe
- Change the shortcut target into something like
C:\xxx\...\python.exe your_script.py
- Click "advance..." in the property panel of the shortcut, and click the option "run as administrator"
- 创建快捷方式
python.exe
- 将快捷方式目标更改为类似
C:\xxx\...\python.exe your_script.py
- 在快捷方式的属性面板中单击“高级...”,然后单击“以管理员身份运行”选项
I'm not sure whether the spells of these options are right, since I'm using Chinese version of Windows.
我不确定这些选项的拼写是否正确,因为我使用的是中文版Windows。
回答by Gary Lee
Here is a solution which needed ctypes module only. Support pyinstaller wrapped program.
这是一个只需要 ctypes 模块的解决方案。支持 pyinstaller 包装的程序。
#!python
# coding: utf-8
import sys
import ctypes
def run_as_admin(argv=None, debug=False):
shell32 = ctypes.windll.shell32
if argv is None and shell32.IsUserAnAdmin():
return True
if argv is None:
argv = sys.argv
if hasattr(sys, '_MEIPASS'):
# Support pyinstaller wrapped program.
arguments = map(unicode, argv[1:])
else:
arguments = map(unicode, argv)
argument_line = u' '.join(arguments)
executable = unicode(sys.executable)
if debug:
print 'Command line: ', executable, argument_line
ret = shell32.ShellExecuteW(None, u"runas", executable, argument_line, None, 1)
if int(ret) <= 32:
return False
return None
if __name__ == '__main__':
ret = run_as_admin()
if ret is True:
print 'I have admin privilege.'
raw_input('Press ENTER to exit.')
elif ret is None:
print 'I am elevating to admin privilege.'
raw_input('Press ENTER to exit.')
else:
print 'Error(ret=%d): cannot elevate privilege.' % (ret, )
回答by John Moore
I can confirm that the solution by delphifirst works and is the easiest, simplest solution to the problem of running a python script with elevated privileges.
我可以确认 delphifirst 的解决方案有效,并且是解决以提升的权限运行 python 脚本问题的最简单、最简单的解决方案。
I created a shortcut to the python executable (python.exe) and then modified the shortcut by adding my script's name after the call to python.exe. Next I checked "run as administrator" on the "compatibility tab" of the shortcut. When the shortcut is executed, you get a prompt asking permission to run the script as an administrator.
我创建了 python 可执行文件 (python.exe) 的快捷方式,然后通过在调用 python.exe 后添加我的脚本名称来修改快捷方式。接下来,我在快捷方式的“兼容性选项卡”上选中了“以管理员身份运行”。执行快捷方式时,会提示您以管理员身份运行脚本。
My particular python application was an installer program. The program allows installing and uninstalling another python app. In my case I created two shortcuts, one named "appname install" and the other named "appname uninstall". The only difference between the two shortcuts is the argument following the python script name. In the installer version the argument is "install". In the uninstall version the argument is "uninstall". Code in the installer script evaluates the argument supplied and calls the appropriate function (install or uninstall) as needed.
我的特定 python 应用程序是一个安装程序。该程序允许安装和卸载另一个 python 应用程序。就我而言,我创建了两个快捷方式,一个名为“appname install”,另一个名为“appname uninstall”。两个快捷方式之间的唯一区别是 python 脚本名称后面的参数。在安装程序版本中,参数是“安装”。在卸载版本中,参数是“卸载”。安装程序脚本中的代码评估提供的参数并根据需要调用适当的函数(安装或卸载)。
I hope my explanation helps others more quickly figure out how to run a python script with elevated privileges.
我希望我的解释可以帮助其他人更快地弄清楚如何以提升的权限运行 python 脚本。
回答by Pranav
Also if your working directory is different than you can use lpDirectory
此外,如果您的工作目录不同于您可以使用 lpDirectory
procInfo = ShellExecuteEx(nShow=showCmd,
lpVerb=lpVerb,
lpFile=cmd,
lpDirectory= unicode(direc),
lpParameters=params)
Will come handy if changing the path is not a desirable option remove unicode for python 3.X
如果更改路径不是一个理想的选项,将派上用场删除 python 3.X 的 unicode
回答by satyamedh
Make sure you have python in path,if not,win key + r, type in "%appdata%"(without the qotes) open local directory, then go to Programs directory ,open python and then select your python version directory. Click on file tab and select copy path and close file explorer.
确保路径中有python,如果没有,win key + r,输入“%appdata%”(不带qotes)打开本地目录,然后转到程序目录,打开python,然后选择你的python版本目录。单击文件选项卡并选择复制路径并关闭文件资源管理器。
Then do win key + r again, type control and hit enter. search for environment variables. click on the result, you will get a window. In the bottom right corner click on environmental variables. In the system side find path, select it and click on edit. In the new window, click on new and paste the path in there. Click ok and then apply in the first window. Restart your PC. Then do win + r for the last time, type cmd and do ctrl + shift + enter. Grant the previliges and open file explorer, goto your script and copy its path. Go back into cmd , type in "python" and paste the path and hit enter. Done
然后再次执行 win key + r ,键入 control 并按回车键。搜索环境变量。单击结果,您将看到一个窗口。在右下角单击环境变量。在系统端找到路径,选择它并点击编辑。在新窗口中,单击新建并将路径粘贴到其中。单击确定,然后在第一个窗口中应用。重新启动您的电脑。然后最后一次win+r,输入cmd,ctrl+shift+回车。授予权限并打开文件资源管理器,转到您的脚本并复制其路径。返回 cmd ,输入“python”并粘贴路径并按回车键。完毕