655

Is there a portable way to get the current user's username in Python (i.e., one that works under both Linux and Windows, at least). It would work like os.getuid:

>>> os.getuid()
42
>>> os.getusername()
'slartibartfast'

I googled around and was surprised not to find a definitive answer (although perhaps I was just googling poorly). The pwd module provides a relatively easy way to achieve this under, say, Linux, but it is not present on Windows. Some of the search results suggested that getting the username under Windows can be complicated in certain circumstances (e.g., running as a Windows service), although I haven't verified that.

Daniel F
  • 11,893
  • 1
  • 21
  • 50
Jacob Gabrielson
  • 29,844
  • 15
  • 44
  • 60

14 Answers14

920

Look at getpass module

import getpass
getpass.getuser()
'kostya'

Availability: Unix, Windows


p.s. Per comment below "this function looks at the values of various environment variables to determine the user name. Therefore, this function should not be relied on for access control purposes (or possibly any other purpose, since it allows any user to impersonate any other)."

omerbp
  • 3,803
  • 3
  • 28
  • 44
Konstantin Tenzin
  • 11,004
  • 2
  • 20
  • 20
  • 107
    It appears that this function looks at the values of various environment variables to determine the user name. Therefore, this function should not be relied on for access control purposes (or possibly any other purpose, since it allows any user to impersonate any other). – Greg Hewgill May 08 '09 at 22:33
  • 31
    There is nothing wrong with getpass.getuser(), since does not claim to authenticate the user. The purpose of the function is to determine who the user is claiming to be without asking the user directly. – Walker Hale IV Oct 17 '11 at 03:47
  • 7
    That does not work if you've done a su. $ echo $USER hithwen $ su julia Password: $ echo $USER julia $ python >>> import getpass >>> getpass.getuser() 'hithwen' – hithwen Jan 23 '13 at 09:56
  • 7
    @GregHewgill raises a very good point, but indeed, finding out the username in a simple unauthenticated way like this does have some applications. My current use-case: tagging some shared testing resources with a username for easy cleanup later. (So it's easier to figure out whose mess is whose.) – driftcatcher Aug 16 '13 at 15:35
  • @hithwen What version are you using? In 2.7.4 your example works as expected for me. – nevelis Feb 26 '14 at 08:25
  • 19
    And I agree with @GregHewgill for the access control purposes, but completely disagree with 'any other purpose' - that's like saying "Don't use $USER in a shell script". Great point about access control but there are *plenty* of other uses that don't involve auth. – nevelis Feb 26 '14 at 08:27
  • 2
    @hithwen That's working as intended. It depends on which arguments you give to `su`. Perhaps you wanted to use `su - julia`. – kasperd Oct 27 '15 at 13:01
  • Doesn't work with sudo! To get the sudo user, I ended up using this: http://unix.stackexchange.com/a/137176/112190 – phyatt Aug 05 '16 at 17:40
  • Works on OSX too, at least as of Sept. 2016! – Delip Sep 17 '16 at 00:04
  • what if we have several users? – Dr. Younes Henni May 30 '18 at 15:25
  • Note that the `USER` variable isn't always set, e.g. in a container. However, I tested `getuser()` in Python 3.6.3 and 2.7.11 with `USER` unset, and it still works. – orodbhen Aug 14 '18 at 13:09
  • Make sure to `SET USERNAME=vmuser` if you're running a Windows VM provided by Microsoft because otherwise this won't work – Neil C. Obremski Apr 29 '20 at 15:41
  • Spasibo Kostya :) – Olshansk Jun 01 '20 at 22:11
  • @Dr.YounesHenni What do you mean? There is always only one user active at any time. – Jann Poppinga Jul 01 '20 at 14:40
136

You best bet would be to combine os.getuid() with pwd.getpwuid():

import os
import pwd

def get_username():
    return pwd.getpwuid( os.getuid() )[ 0 ]

Refer to the pwd docs for more details:

http://docs.python.org/library/pwd.html

GreenMatt
  • 16,928
  • 6
  • 49
  • 75
Liam Chasteen
  • 1,561
  • 1
  • 9
  • 2
101

You can also use:

 os.getlogin()
Marcin Augustyniak
  • 1,091
  • 1
  • 7
  • 2
  • 34
    On linux, getlogin() returns the name of the "user logged in on the controlling terminal of the process." It therefore fails when there is no controlling terminal, e.g., in a mod_python application. – Vebjorn Ljosa Nov 10 '09 at 23:56
  • 4
    If you used su, then this won't return the current user, but the originally logged in user. – Trevor Allred Sep 18 '14 at 17:26
  • 5
    does work on windows...Python 3.4.1 (v3.4.1:c0e311e010fc, May 18 2014, 10:38:22) [MSC v.1600 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import os; os.getlogin() 'jrb' – Naib Oct 22 '14 at 12:20
  • 6
    It's only available on Windows for Python 3.x. – Zitrax Sep 09 '15 at 12:37
  • 1
    Thanks for this. The login user is not exactly what the poster asked for but it is what I was looking for. – jorfus Mar 03 '16 at 19:20
  • On linux, `os.path.basename(os.listdir('/home')[0])` is more reliable across systems (e.g., desktop vs raspberry pi), assuming you are the only user of course. – Justapigeon Jan 06 '20 at 01:01
  • @WalkerHaleIV - what are you talking about?!? Yes it is! What isn't available is os.getuid. And pwd, at all. – Poke Jun 24 '20 at 13:55
  • On MacOS it is just giving me 'root' even though I am not logged in as root. – Christopher Barber Dec 15 '20 at 20:59
82

You can probably use:

os.environ.get('USERNAME')

or

os.environ.get('USER')

But it's not going to be safe because environment variables can be changed.

Aaron McDaid
  • 24,484
  • 9
  • 56
  • 82
Nadia Alramli
  • 99,188
  • 32
  • 168
  • 151
24

These might work. I don't know how they behave when running as a service. They aren't portable, but that's what os.name and ifstatements are for.

win32api.GetUserName()

win32api.GetUserNameEx(...) 

See: http://timgolden.me.uk/python/win32_how_do_i/get-the-owner-of-a-file.html

ncica
  • 6,018
  • 1
  • 12
  • 30
Adam
  • 320
  • 2
  • 3
  • 32
    This answer is at least as useful as the (useless) 25-vote upvoted unix-only answer. – Tom B Feb 14 '12 at 18:27
  • 5
    >"At least as useful" Agreed. Presumably the right answer is a combination of the two. – Jonathan Hartley Aug 02 '14 at 16:50
  • If you're stuck on python 2 on Windows, this is the only safe way to do it. All the other ways can be tricked by running ```SET USERNAME=FAKE``` before your python command – CodeKid Jan 21 '19 at 17:22
21

If you are needing this to get user's home dir, below could be considered as portable (win32 and linux at least), part of a standard library.

>>> os.path.expanduser('~')
'C:\\Documents and Settings\\johnsmith'

Also you could parse such string to get only last path component (ie. user name).

See: os.path.expanduser

HezniK
  • 235
  • 2
  • 2
17

To me using os module looks the best for portability: Works best on both Linux and Windows.

import os

# Gives user's home directory
userhome = os.path.expanduser('~')          

print "User's home Dir: " + userhome

# Gives username by splitting path based on OS
print "username: " + os.path.split(userhome)[-1]           

Output:

Windows:

User's home Dir: C:\Users\myuser

username: myuser

Linux:

User's home Dir: /root

username: root

No need of installing any modules or extensions.

  • 22
    This solution is clever, but makes some assumptions that aren't always true. There is no constraint that requires the username to appear in the homedir path on Linux. It just happens to be the case most of the time, but a sysadmin can set a user's homedir to whatever they want. – Joe Holloway Aug 04 '14 at 15:04
  • 1
    Setting the HOME variable defeats this. – GLRoman Apr 22 '20 at 22:02
13

Combined pwd and getpass approach, based on other answers:

try:
  import pwd
except ImportError:
  import getpass
  pwd = None

def current_user():
  if pwd:
    return pwd.getpwuid(os.geteuid()).pw_name
  else:
    return getpass.getuser()
anatoly techtonik
  • 17,421
  • 8
  • 111
  • 131
8

For UNIX, at least, this works...

import commands
username = commands.getoutput("echo $(whoami)")
print username

edit: I just looked it up and this works on Windows and UNIX:

import commands
username = commands.getoutput("whoami")

On UNIX it returns your username, but on Windows, it returns your user's group, slash, your username.

--

I.E.

UNIX returns: "username"

Windows returns: "domain/username"

--

It's interesting, but probably not ideal unless you are doing something in the terminal anyway... in which case you would probably be using os.system to begin with. For example, a while ago I needed to add my user to a group, so I did (this is in Linux, mind you)

import os
os.system("sudo usermod -aG \"group_name\" $(whoami)")
print "You have been added to \"group_name\"! Please log out for this to take effect"

I feel like that is easier to read and you don't have to import pwd or getpass.

I also feel like having "domain/user" could be helpful in certain applications in Windows.

HoldOffHunger
  • 10,963
  • 6
  • 53
  • 100
dylnmc
  • 3,276
  • 3
  • 20
  • 37
  • 1
    WIndows returns `domain/user` not `group/user` – RealHowTo Nov 04 '14 at 19:41
  • 4
    The commands module does not work on Windows. It's a UNIX specific module (see https://docs.python.org/2/library/commands.html). It's now deprecated and subprocess is recommended instead. `user = subprocess.check_output("whoami").replace("\r\n", "")` – ConnectedSystems Dec 03 '16 at 04:59
  • 2 remarks. commands.whoami did great, even in the context of a service running under a different username. i.e. with `chpst -u nobody python ./manage.py celerycam --pidfile=/var/run/celerycam/celerycam.pid ` I got **nobody**. second, `user = subprocess.check_output("whoami").strip()` is more portable than the replace linefeeds above. `commands` vs `subprocess` seems nitpicky but commands is missing from python 3. – JL Peyret Dec 21 '17 at 01:11
8

psutil provides a portable way that doesn't use environment variables like the getpass solution. It is less prone to security issues, and should probably be the accepted answer as of today.

import psutil

def get_username():
    return psutil.Process().username()

Under the hood, this combines the getpwuid based method for unix and the GetTokenInformation method for Windows.

Erik Aronesty
  • 8,927
  • 4
  • 46
  • 29
6

Using only standard python libs:

from os import environ,getcwd
getUser = lambda: environ["USERNAME"] if "C:" in getcwd() else environ["USER"]
user = getUser()

Works on Windows (if you are on drive C), Mac or Linux

Alternatively, you could remove one line with an immediate invocation:

from os import environ,getcwd
user = (lambda: environ["USERNAME"] if "C:" in getcwd() else environ["USER"])()
ThisGuyCantEven
  • 739
  • 8
  • 19
  • 2
    getpass is also a standard lib – jodag Feb 12 '20 at 21:50
  • doesnt work for me in win10, python3.7.4. its complaining about 'USER' not being found in envirnment variables I guess. I guess getpass is a better choice anyway. – Rika Jun 06 '20 at 07:15
  • The only thing that would cause this is if you run it from a drive other than `C:`. That is the only reason it would use the `USER` key and not `USERNAME`. This is literally just an if/else... All it does is use `USERNAME` if there is a `C:` drive else `USER` – ThisGuyCantEven Jul 09 '20 at 14:56
4

I wrote the plx module some time ago to get the user name in a portable way on Unix and Windows (among other things): http://www.decalage.info/en/python/plx

Usage:

import plx

username = plx.get_username()

(it requires win32 extensions on Windows)

decalage
  • 65
  • 1
  • 1
3

You can get the current username on Windows by going through the Windows API, although it's a bit cumbersome to invoke via the ctypes FFI (GetCurrentProcessOpenProcessTokenGetTokenInformationLookupAccountSid).

I wrote a small module that can do this straight from Python, getuser.py. Usage:

import getuser
print(getuser.lookup_username())

It works on both Windows and *nix (the latter uses the pwd module as described in the other answers).

Michael Kropat
  • 12,704
  • 9
  • 64
  • 85
1

None of the above worked in my case (scroll down to the actual solution).
The problem I'm getting with all solutions is the wrong username when running commands with sudo:

  • psutil soulution:
$ python3
>>> import psutil
>>> psutil.Process().username()
'ubuntu' # OK!

$ sudo su
$ python3
>>> import psutil
>>> psutil.Process().username()
'root' # OK!

$ sudo python3
>>> import psutil
>>> psutil.Process().username()
'root' # WRONG, should be ubuntu!
  • getpass solution:
$ python3
>>> import getpass
>>> getpass.getuser()
'ubuntu' # OK!

$ sudo su
$ python3
>>> import getpass
>>> getpass.getuser()
'root' # OK!

$ sudo python3
>>> import getpass
>>> getpass.getuser()
'root' # WRONG, should be ubuntu!
  • pwd + os.getuid solution:
$ python3
>>> import os, pwd
>>> pwd.getpwuid( os.getuid() )[ 0 ]
'ubuntu' # OK!

$ sudo su
$ python3
>>> import os, pwd
>>> pwd.getpwuid( os.getuid() )[ 0 ]
'root' # OK!

$ sudo python3
>>> import getpass
>>> getpass.getuser()
'root' # WRONG, should be ubuntu!
  • os.getlogin works a bit different, but still wrong:
$ python3
>>> import os
>>> os.getlogin()
'ubuntu' # OK!

$ sudo su
$ python3
>>> import os
>>> os.getlogin()
'ubuntu' # WRONG, should be root!


$ sudo python3
>>> import os
>>> os.getlogin()
'ubuntu' # OK!
  • os.getenv gives the same results:
$ python3
>>> import os
>>> os.getenv('SUDO_USER', os.getenv('USER'))
'ubuntu' # OK!

$ sudo su
$ python3
>>> import os
>>> os.getenv('SUDO_USER', os.getenv('USER'))
'ubuntu' # WRONG, should be root!


$ sudo python3
>>> import os
>>> os.getenv('SUDO_USER', os.getenv('USER'))
'ubuntu' # OK!

Switching SUDO_USER and USER gives the wrong result in sudo python3 case.

Actual solution (non-portable)

Solution is a bit tricky and rely on the default root home directory location but works for all cases:

$ python3
>>> import os
>>> 'root' if os.path.expanduser('~') == '/root' else os.getenv('SUDO_USER', os.getenv('USER'))
'ubuntu' # OK!

$ sudo su
$ python3
>>> import os
>>> 'root' if os.path.expanduser('~') == '/root' else os.getenv('SUDO_USER', os.getenv('USER'))
'root' #  OK!

$ sudo python3
>>> import os
>>> 'root' if os.path.expanduser('~') == '/root' else os.getenv('SUDO_USER', os.getenv('USER'))
'ubuntu' # OK!
Dmitry T.
  • 396
  • 2
  • 9