Is there a portable way to get the current username in Python?
Asked Answered
D

15

768

What is a portable way (e.g. for Linux and Windows) to get the current user's username? Something similar to os.getuid() would be nice:

>>> os.getuid()
42

# Does not currently exist in Python
>>> os.getusername()
'slartibartfast'

The pwd module works for Unix only. Some people suggest that getting the username under Windows can be complicated in certain circumstances (e.g., running as a Windows service).

Duvetyn answered 8/5, 2009 at 22:20 Comment(2)
import pwd, os; print pwd.getpwuid(os.getuid()).pw_gecos or import pwd, os; print pwd.getpwuid(os.getuid()).pw_nameMande
"username" is not even a portable concept. Consider microPython -- if you're running directly on hardware there's no such thing.Heid
T
1075

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)."

Thermal answered 8/5, 2009 at 22:30 Comment(17)
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.Thermolabile
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'Cooley
@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.)Clearing
@Cooley What version are you using? In 2.7.4 your example works as expected for me.Chamaeleon
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.Chamaeleon
@Cooley That's working as intended. It depends on which arguments you give to su. Perhaps you wanted to use su - julia.Coverlet
Doesn't work with sudo! To get the sudo user, I ended up using this: unix.stackexchange.com/a/137176/112190Advertising
Works on OSX too, at least as of Sept. 2016!Strata
what if we have several users?Aloysius
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.Florri
Make sure to SET USERNAME=vmuser if you're running a Windows VM provided by Microsoft because otherwise this won't workFrater
@Dr.YounesHenni What do you mean? There is always only one user active at any time.Belligerent
@Advertising It works as intended. The user is root when you're running with sudo. If you want to get the user who called sudo, that's a different question.Evalyn
getpass is part of the standard library.Fuliginous
plus 1 = 1000. Congrats :)Silures
This does not work reliably. Why? Because it will just read USER, USERNAME, LNAME, LOGUSER environment variables (check the source). Each of these can be overriden but there is still a "real" current user (e.g by invoking a subprocess running id -un)Dex
E.g. run LOGNAME=dumb python -c "import getpass;print(getpass.getuser())"Dex
W
173

Combine os.getuid() with pwd.getpwuid():

import os
import pwd

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

See pwd docs for more details.

Wetzel answered 24/5, 2010 at 17:53 Comment(7)
Alternatively (slightly nicer to read): pwd.getpwuid(os.getuid()).pw_name.Gagarin
What does it do on Windows? Perhaps one could try this, and if it fails, fall back to the crappy 'getpass/env var' methods.Tami
This is the correct way if you need to get the username both with and without logging in.Discommend
@JonathanHartley: ImportError: No module named pwdOdie
This method is on unix-like systems much superior to Konstantin Tenzin's answer, because it handles the sudo case correctly. (I am aware the OP didn';t ask for unix-like ssytems.)Sahib
@Sahib When running with sudo, the expected behavior is for it to return root. That is by design and the other answers are not "wrong". You are simply asking for the answer to a different question.Evalyn
Wrong answer -- this is NOT portable to Windows.Leontina
H
131

You can also use:

os.getlogin()
Hulda answered 20/10, 2009 at 13:0 Comment(8)
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.Cheng
If you used su, then this won't return the current user, but the originally logged in user.Ova
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'Whippoorwill
It's only available on Windows for Python 3.x.Grantgranta
Thanks for this. The login user is not exactly what the poster asked for but it is what I was looking for.Preposition
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.Maneating
@WalkerHaleIV - what are you talking about?!? Yes it is! What isn't available is os.getuid. And pwd, at all.Tannen
On MacOS it is just giving me 'root' even though I am not logged in as root.Antiphonary
C
111

Windows:

os.environ.get('USERNAME')

Linux:

os.environ.get('USER')

Both:

os.environ.get('USER', os.environ.get('USERNAME'))

Note that environment variables can be modified by the user, so this is a potential security vulnerability. With this method, an attacker can easily fake their username.

Claudie answered 8/5, 2009 at 22:35 Comment(9)
os.getenv(...) is deprecated in favour of os.environ[...].Aluminate
Shouldn't it be USER instead of USERNAME?Lomond
@MikeGraham os.getenv doesn't seem to be deprecated..?Kinna
Yes, exactly USER vs USERNAME is exactly what is not portable, so it doesn't provide the correct answer.Castro
USERNAME is for Windows, USER is for LinuxSurgical
USER is not present for my test with PythonWin GUI window.Ephemeris
@AlexanderStohr Exactly, therefore also USERNAME is queried in the expression.Loutish
just noted it down for illustrating how "complicated" a specific scenario assignment might turn out.Ephemeris
The fact that the user can change the environment variables is NOT a security vulnerability. If doing that can cause a problem, it's indicative of a larger problem with the server-side of your application lacking proper authentication, and adjusting client-side code to obtain the username though some other means will not actually fix the underlying problem.Linear
M
25

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

Mucky answered 2/1, 2010 at 21:35 Comment(3)
This answer is at least as useful as the (useless) 25-vote upvoted unix-only answer.Valonia
>"At least as useful" Agreed. Presumably the right answer is a combination of the two.Tami
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 commandLattermost
M
23

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

Marjana answered 9/2, 2013 at 1:23 Comment(2)
Someone's home directory does not always reflect their username.Pase
Unfortunately, if you set the HOME variable in Windows, this will return it that value.Anuran
K
19

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.

Kamalakamaria answered 9/12, 2020 at 20:10 Comment(2)
Is there a function in there to get it without the domain or do I split it on the / ?Olson
split on the "\\" if present, yes, see: github.com/giampaolo/psutil/issues/1049Kamalakamaria
C
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.

Czardas answered 5/12, 2013 at 14:39 Comment(2)
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.Rizzi
Setting the HOME variable defeats this.Anuran
D
15

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()
Desrosiers answered 8/11, 2013 at 17:47 Comment(2)
getpass.getuser() Retrieves non-empty string from these environment variables LOGNAME, USER, LNAME and USERNAME, in order. If none are set, then login name from password database is returned on systems which support pwd module, else raises exception. pw_name is also login nameCardiology
I might only use the pwd side, but this is the only answer here that gets the name of the effective user ID.Phina
P
7

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.

Pituri answered 16/9, 2014 at 17:31 Comment(4)
WIndows returns domain/user not group/userArchil
The commands module does not work on Windows. It's a UNIX specific module (see docs.python.org/2/library/commands.html). It's now deprecated and subprocess is recommended instead. user = subprocess.check_output("whoami").replace("\r\n", "")Smallclothes
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.Sailor
-1 for using unsafe methods, at the very least you should be using subprocess, but spawning a separate process for this is excessive regardless.Evalyn
B
7

Using only standard python libs:

from os import environ
from sys import platform

def getUser():
    return environ["USERNAME"] if platform.startswith("win") else environ["USER"]

user = getUser()

Works on Windows, Mac or Linux.

Bosquet answered 13/5, 2019 at 13:47 Comment(5)
getpass is also a standard libEbneter
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.Storz
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 USERBosquet
This is just a hacky solution and will break if your current working directory is on another drive. Your answer doesn't really provide a benefit over the others. There are better ways to check the platform even if you wanted to go that way, but usually it's preferable to use something that's portable from the start.Evalyn
@Rob Grant good editBosquet
G
5

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!
Guaiacum answered 28/4, 2021 at 11:47 Comment(4)
This is the answer to a very different questionPsychoneurosis
But grateful for it - deals with the sudo issue for that very different question for those looking for the answer to it from a Google search that leads here. Perhaps only a somewhat different question.Ranchman
sudo escalates so root is effectively the user. if you want to be able to define your own user, I recommend creating a -u/--user flag so you can do something like sudo ./foo.py -u myUser, etcPituri
As the others said, the result you are getting is not wrong. The command is running as root for all intents and purposes. This may be useful to someone but it's not an answer to OP's question.Evalyn
P
3

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)

Photoemission answered 4/2, 2010 at 19:52 Comment(0)
P
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).

Planometer answered 20/11, 2013 at 8:12 Comment(0)
H
-4

this works for me:

import os
os.cmd("whoami")
print (os.cmd("whoami"))
Heinrik answered 26/8, 2022 at 19:17 Comment(4)
There is no os.cmd. Is this Python's built-in os module?Employ
yes the built-in os module. running Python 3.7 running on a Pi4B with RaspberryOS Buster.Heinrik
Hmm, interesting, because it's not listed in the Python 3.7 docs for the os module.Employ
hhmmm a non-documented feature. normally called a "bug" :-)Heinrik

© 2022 - 2024 — McMap. All rights reserved.