[英]Get root dialog in Python on Mac OS X, Windows?
我如何獲得在我的Python應用程序中彈出的權限提升對話框? 我想要Windows上的UAC對話框和Mac上的密碼驗證對話框。
基本上,我需要部分應用程序的root權限,我需要通過GUI獲得這些權限。 我正在使用wxPython。 有任何想法嗎?
在Windows上,如果不啟動新進程,則無法獲取UAC對話框,甚至無法使用CreateProcess啟動該進程。
可以通過運行具有相應清單文件的另一個應用程序來實現UAC對話框 - 請參閱在Vista中以管理員身份運行編譯的python(py2exe),以獲取如何使用py2exe執行此操作的示例。
你也可以編程方式使用runas動詞與win32 api ShellExecute http://msdn.microsoft.com/en-us/library/bb762153(v=vs.85).aspx - 你可以通過使用ctypes來調用它:http:/ /python.net/crew/theller/ctypes/是python 2.5+ iirc上標准庫的一部分。
抱歉,不知道Mac。 如果您提供有關要在Windows上完成的內容的更多詳細信息,我可以提供更具體的幫助。
我知道帖子有點舊,但我寫了以下內容作為我的問題的解決方案(在Linux和OS X上以root身份運行python腳本)。
我編寫了以下bash腳本來執行具有管理員權限的bash / python腳本(適用於Linux和OS X系統):
#!/bin/bash
if [ -z "$1" ]; then
echo "Specify executable"
exit 1
fi
EXE=$1
available(){
which $1 >/dev/null 2>&1
}
platform=`uname`
if [ "$platform" == "Darwin" ]; then
MESSAGE="Please run $1 as root with sudo or install osascript (should be installed by default)"
else
MESSAGE="Please run $1 as root with sudo or install gksu / kdesudo!"
fi
if [ `whoami` != "root" ]; then
if [ "$platform" == "Darwin" ]; then
# Apple
if available osascript
then
SUDO=`which osascript`
fi
else # assume Linux
# choose either gksudo or kdesudo
# if both are avilable check whoch desktop is running
if available gksudo
then
SUDO=`which gksudo`
fi
if available kdesudo
then
SUDO=`which kdesudo`
fi
if ( available gksudo && available kdesudo )
then
if [ $XDG_CURRENT_DESKTOP = "KDE" ]; then
SUDO=`which kdesudo`;
else
SUDO=`which gksudo`
fi
fi
# prefer polkit if available
if available pkexec
then
SUDO=`which pkexec`
fi
fi
if [ -z $SUDO ]; then
if available zenity; then
zenity --info --text "$MESSAGE"
exit 0
elif available notify-send; then
notify-send "$MESSAGE"
exit 0
elif available xmessage notify-send; then
xmessage -buttons Ok:0 "$MESSAGE"
exit 0
else
echo "$MESSAGE"
fi
fi
fi
if [ "$platform" == "Darwin" ]
then
$SUDO -e "do shell script \"$*\" with administrator privileges"
else
$SUDO $@
fi
基本上,我設置系統的方式是將子文件夾保存在bin目錄中(例如/ usr / local / bin中的/ usr / local / bin / pyscripts),並創建指向可執行文件的符號鏈接。 這對我有三個好處:
(1)如果我有不同的版本,我可以通過更改符號鏈接輕松切換執行哪個版本,並使bin目錄保持清潔(例如/usr/local/bin/gcc-versions/4.9/,/ usr / local / bin / gcc-versions / 4.8 /,/ usr / local / bin / gcc - > gcc-versions / 4.8 / gcc)
(2)我可以使用它們的擴展名存儲腳本(有助於IDE中的語法高亮顯示),但可執行文件不包含它們,因為我喜歡它(例如svn-tools - > pyscripts / svn-tools.py)
(3)我將在下面顯示的原因:
我將腳本命名為“run-as-root-wrapper”並將其放在一個非常常見的路徑中(例如/ usr / local / bin),因此python不需要任何特殊的東西來定位它。 然后我有以下run_command.py模塊:
import os
import sys
from distutils.spawn import find_executable
#===========================================================================#
def wrap_to_run_as_root(exe_install_path, true_command, expand_path = True):
run_as_root_path = find_executable("run-as-root-wrapper")
if(not run_as_root_path):
return False
else:
if(os.path.exists(exe_install_path)):
os.unlink(exe_install_path)
if(expand_path):
true_command = os.path.realpath(true_command)
true_command = os.path.abspath(true_command)
true_command = os.path.normpath(true_command)
f = open(exe_install_path, 'w')
f.write("#!/bin/bash\n\n")
f.write(run_as_root_path + " " + true_command + " $@\n\n")
f.close()
os.chmod(exe_install_path, 0755)
return True
在我的實際python腳本中,我有以下功能:
def install_cmd(args):
exe_install_path = os.path.join(args.prefix,
os.path.join("bin", args.name))
if(not run_command.wrap_to_run_as_root(exe_install_path, sys.argv[0])):
os.symlink(os.path.realpath(sys.argv[0]), exe_install_path)
因此,如果我有一個名為TrackingBlocker.py的腳本(我用來修改/ etc / hosts文件以將已知跟蹤域重新路由到127.0.0.1的實際腳本),當我調用“sudo / usr / local / bin / pyscripts /”時TrackingBlocker.py --prefix / usr / local --name ModifyTrackingBlocker install“(通過argparse模塊處理的參數),它安裝”/ usr / local / bin / ModifyTrackingBlocker“,這是一個bash腳本執行
/usr/local/bin/run-as-root-wrapper /usr/local/bin/pyscripts/TrackingBlocker.py [args]
例如
ModifyTrackingBlocker add tracker.ads.com
執行:
/usr/local/bin/run-as-root-wrapper /usr/local/bin/pyscripts/TrackingBlocker.py add tracker.ads.com
然后顯示獲取添加權限所需的身份驗證對話框:
127.0.0.1 tracker.ads.com
到我的主機文件(只能由超級用戶寫入)。
如果您想簡化/修改它以僅以root身份運行某些命令,您只需將其添加到您的腳本中(使用上面提到的必要導入+ import subprocess):
def run_as_root(command, args, expand_path = True):
run_as_root_path = find_executable("run-as-root-wrapper")
if(not run_as_root_path):
return 1
else:
if(expand_path):
command = os.path.realpath(command)
command = os.path.abspath(command)
command = os.path.normpath(command)
cmd = []
cmd.append(run_as_root_path)
cmd.append(command)
cmd.extend(args)
return subprocess.call(' '.join(cmd), shell=True)
使用上面的(在run_command模塊中):
>>> ret = run_command.run_as_root("/usr/local/bin/pyscripts/TrackingBlocker.py", ["status", "display"])
>>> /etc/hosts is blocking approximately 16147 domains
我在Mac OS X上遇到了同樣的問題。我有一個可行的解決方案,但它並不是最佳的。 我將在這里解釋我的解決方案並繼續尋找更好的解決方案。
在程序開始時,我通過執行檢查我是否是root用戶
def _elevate():
"""Elevate user permissions if needed"""
if platform.system() == 'Darwin':
try:
os.setuid(0)
except OSError:
_mac_elevate()
os.setuid(0)將失敗,如果我還不是root,那將觸發_mac_elevate(),它在管理員的幫助下從osascript開始重新啟動我的程序。 osascript可用於執行applescript和其他東西。 我這樣使用它:
def _mac_elevate():
"""Relaunch asking for root privileges."""
print "Relaunching with root permissions"
applescript = ('do shell script "./my_program" '
'with administrator privileges')
exit_code = subprocess.call(['osascript', '-e', applescript])
sys.exit(exit_code)
這個問題是如果我使用subprocess.call,如上所述我保持當前進程運行,我的應用程序將運行兩個實例,給出兩個停靠圖標。 如果我使用subprocess.Popen而讓非特權進程立即死亡我無法使用退出代碼,也無法獲取stdout / stderr流並傳播到終端開始原始進程。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.