Request UAC elevation from within a Python script?

It took me a little while to get dguaraglia's answer working, so in the interest of saving others time, here's what I did to implement this idea:

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)

As of 2017, an easy method to achieve this is the following:

import ctypes, sys

def is_admin():
    try:
        return ctypes.windll.shell32.IsUserAnAdmin()
    except:
        return False

if is_admin():
    # Code of your program here
else:
    # Re-run the program with admin rights
    ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, " ".join(sys.argv), None, 1)

If you are using Python 2.x, then you should replace the last line for:

ctypes.windll.shell32.ShellExecuteW(None, u"runas", unicode(sys.executable), unicode(" ".join(sys.argv)), None, 1)

Also note that if you converted you python script into an executable file (using tools like py2exe, cx_freeze, pyinstaller) then you should use sys.argv[1:] instead of sys.argv in the fourth parameter.

Some of the advantages here are:

  • No external libraries required. It only uses ctypes and sys from standard library.
  • Works on both Python 2 and Python 3.
  • There is no need to modify the file resources nor creating a manifest file.
  • If you don't add code below if/else statement, the code won't ever be executed twice.
  • You can get the return value of the API call in the last line and take an action if it fails (code <= 32). Check possible return values here.
  • You can change the display method of the spawned process modifying the sixth parameter.

Documentation for the underlying ShellExecute call is here.