Czy istnieje przenośny sposób na uzyskanie bieżącej nazwy użytkownika w Pythonie?

596

Czy istnieje przenośny sposób na uzyskanie nazwy użytkownika bieżącego użytkownika w Pythonie (tj. Takiej, która działa przynajmniej pod Linuksem i Windows). Działa to tak os.getuid:

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

Gogłem w kółko i byłem zaskoczony, że nie znalazłem ostatecznej odpowiedzi (chociaż być może po prostu źle googlowałem). Pwd Moduł zapewnia stosunkowo łatwy sposób, aby osiągnąć to pod, powiedzmy, Linux, ale nie jest obecny w systemie Windows. Niektóre wyniki wyszukiwania sugerowały, że uzyskanie nazwy użytkownika w systemie Windows może być skomplikowane w pewnych okolicznościach (np. Działanie jako usługa systemu Windows), chociaż tego nie zweryfikowałem.

Jacob Gabrielson
źródło
To nie działa na moim Linux-ie!
Riccardo,
4
import pwd, os; print pwd.getpwuid(os.getuid()).pw_gecoslubimport pwd, os; print pwd.getpwuid(os.getuid()).pw_name
chown
getusername () nie jest poprawną metodą w module OS Python: docs.python.org/2.7/library/os.html
Matt Bruzek
17
@MattBruzek To był punkt OP. Wyobraził sobie, jak można by wywołać taką funkcję, gdyby istniała.
poke

Odpowiedzi:

836

Spójrz na moduł getpass

import getpass
getpass.getuser()
'kostya'

Dostępność: Unix, Windows


ps W komentarzu poniżej ” ta funkcja sprawdza wartości różnych zmiennych środowiskowych w celu ustalenia nazwy użytkownika. Dlatego nie należy polegać na tej funkcji do celów kontroli dostępu (lub ewentualnie w jakimkolwiek innym celu, ponieważ pozwala każdemu użytkownikowi na podszywanie się pod inne osoby) ).

Konstantin Tenzin
źródło
100
Wygląda na to, że ta funkcja sprawdza wartości różnych zmiennych środowiskowych w celu ustalenia nazwy użytkownika. Dlatego nie należy polegać na tej funkcji do celów kontroli dostępu (lub ewentualnie w jakimkolwiek innym celu, ponieważ umożliwia ona podszywanie się pod inne osoby).
Greg Hewgill,
25
Nie ma nic złego w getpass.getuser (), ponieważ nie twierdzi, że uwierzytelnia użytkownika. Celem tej funkcji jest ustalenie, kim jest użytkownik, bez pytania go bezpośrednio.
Walker Hale IV
7
To nie działa, jeśli zrobiłeś su. $ echo $ USER hithwen $ su julia Hasło: $ echo $ USER julia $ python >>> import getpass >>> getpass.getuser () 'hithwen'
hithwen
6
@GregHewgill podnosi bardzo dobry punkt, ale w rzeczywistości znalezienie nazwy użytkownika w prosty, nieuwierzytelniony sposób, taki jak ten, ma pewne aplikacje. Mój obecny przypadek użycia: oznaczenie niektórych współużytkowanych zasobów testowych nazwą użytkownika w celu późniejszego łatwego wyczyszczenia. (Więc łatwiej jest ustalić, czyj to bałagan.)
driftcatcher 16.08.13
16
I zgadzam się z @GregHewgill do celów kontroli dostępu, ale całkowicie nie zgadzam się z „jakimkolwiek innym celem” - to tak, jakby powiedzieć „Nie używaj $ USER w skrypcie powłoki”. Świetna uwaga na temat kontroli dostępu, ale istnieje wiele innych zastosowań, które nie wymagają uwierzytelnienia.
nevelis
119

Najlepiej byłoby połączyć os.getuid()z pwd.getpwuid():

import os
import pwd

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

Więcej informacji można znaleźć w dokumentach pwd:

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

Liam Chasteen
źródło
51
Alternatywnie (nieco ładniejszy, aby przeczytać) pwd.getpwuid(os.getuid()).pw_name.
Brian M. Hunt
6
Co robi w systemie Windows? Być może można by tego spróbować, a jeśli to się nie powiedzie, powróć do gównianych metod „getpass / env var”.
Jonathan Hartley,
2
Jest to poprawny sposób, jeśli chcesz uzyskać nazwę użytkownika zarówno podczas logowania, jak i bez niego.
Derrick Zhang,
5
@JonathanHartley:ImportError: No module named pwd
Justin
1
Ta metoda działa w systemach uniksowych znacznie lepszych niż odpowiedź Konstantina Tenzina, ponieważ sudopoprawnie obsługuje skrzynkę. (Wiem, że OP nie zrobił; nie prosiłem o uniksopodobne
ssytems
86

Możesz także użyć:

 os.getlogin()
Marcin Augustyniak
źródło
29
W systemie Linux getlogin () zwraca nazwę „użytkownika zalogowanego na terminalu sterującym procesu”. Dlatego kończy się niepowodzeniem, gdy nie ma terminala sterującego, np. W aplikacji mod_python.
Vebjorn Ljosa,
23
Niedostępne dla systemu Windows
Walker Hale IV
3
Jeśli użyłeś su, nie zwróci to bieżącego użytkownika, ale pierwotnie zalogowanego użytkownika.
Trevor Allred,
4
działa w systemie Windows ... Python 3.4.1 (v3.4.1: c0e311e010fc, 18 maja 2014, 10:38:22) [MSC v.1600 32 bit (Intel)] na win32 Wpisz „help”, „copyright”, „kredyty” lub „licencja”, aby uzyskać więcej informacji. >>> import os; os.getlogin () 'jrb'
Naib
5
Jest dostępny tylko w systemie Windows dla Python 3.x.
Zitrax
71

Prawdopodobnie możesz użyć:

os.environ.get('USERNAME')

lub

os.environ.get('USER')

Ale to nie będzie bezpieczne, ponieważ zmienne środowiskowe można zmieniać.

Nadia Alramli
źródło
18
os.getenv(...)jest przestarzałe na korzyść os.environ[...].
Mike Graham
11
Czy nie powinien to być USER zamiast USERNAME?
Karl Bartel
7
@MikeGraham os.getenvnie wydaje się być przestarzały ..?
dbr
4
Tak, dokładnie USER vs USERNAME jest dokładnie tym, co nie jest przenośne, więc nie zawiera poprawnej odpowiedzi.
Peter M
2
USERNAME jest dla systemu Windows, USER jest dla systemu Linux
Sabrina
22

Te mogą działać. Nie wiem, jak się zachowują, gdy działają jako usługa. Nie są przenośne, ale do tego właśnie służą os.namei ifstwierdzenia.

win32api.GetUserName()

win32api.GetUserNameEx(...) 

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

Adam
źródło
30
Ta odpowiedź jest co najmniej tak przydatna, jak (bezużyteczna) 25-głosowa poprawiona odpowiedź tylko na system uniksowy.
Tom B
3
> Uzgodniono „Przynajmniej tak przydatne”. Prawdopodobnie właściwa odpowiedź jest kombinacją tych dwóch.
Jonathan Hartley,
Jeśli utkniesz w Pythonie 2 w systemie Windows, jest to jedyny bezpieczny sposób, aby to zrobić. Wszystkie inne sposoby można oszukać, uruchamiając SET USERNAME=FAKEprzed poleceniem w Pythonie
CodeKid
21

Jeśli potrzebujesz tego, aby uzyskać katalog domowy użytkownika, poniżej można go uznać za przenośny (przynajmniej Win32 i Linux), będący częścią standardowej biblioteki.

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

Można również przeanalizować taki ciąg, aby uzyskać tylko ostatni składnik ścieżki (tj. Nazwę użytkownika).

Zobacz: os.path.expanduser

HezniK
źródło
9
Czyjś katalog domowy nie zawsze odzwierciedla jego nazwę użytkownika.
dreamlax
Działa to zarówno w systemie Linux, jak i Windows
Sabrina
Niestety, jeśli ustawisz zmienną HOME w Windows, zwróci ona tę wartość.
GLRoman
15

Dla mnie użycie osmodułu wygląda najlepiej pod względem przenośności: Działa najlepiej zarówno w systemie Linux, jak i 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]           

Wynik:

Windows:

Dom użytkownika, reż: C: \ Users \ myuser

nazwa użytkownika: mój użytkownik

Linux:

Strona główna użytkownika Katalog: / root

nazwa użytkownika: root

Nie ma potrzeby instalowania żadnych modułów ani rozszerzeń.


źródło
16
To rozwiązanie jest sprytne, ale zawiera pewne założenia, które nie zawsze są prawdziwe. Nie ma żadnych ograniczeń, które wymagają, aby nazwa użytkownika pojawiała się na ścieżce katalogu głównego w systemie Linux. Tak się składa, że ​​dzieje się tak przez większość czasu, ale sysadmin może ustawić homedir użytkownika na cokolwiek zechce.
Joe Holloway,
Ustawienie zmiennej HOME eliminuje to.
GLRoman
11

Połączone pwdi getpasspodejście oparte na innych odpowiedziach:

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
źródło
9

Przynajmniej w przypadku systemu UNIX działa to ...

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

edycja: Właśnie to sprawdziłem i działa to w systemach Windows i UNIX:

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

W systemie UNIX zwraca nazwę użytkownika, ale w systemie Windows zwraca grupę użytkownika, ukośnik, nazwę użytkownika.

-

TO ZNACZY

Zwraca UNIX: „nazwa użytkownika”

System Windows zwraca: „domena / nazwa użytkownika”

-

Jest to interesujące, ale prawdopodobnie nie idealne, chyba że i tak robisz coś w terminalu ... w takim przypadku prawdopodobnie używałbyś os.systemna początku. Na przykład jakiś czas temu musiałem dodać mojego użytkownika do grupy, więc zrobiłem to (jest to w Linuksie, pamiętajcie)

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"

Wydaje mi się, że jest to łatwiejsze do odczytania i nie trzeba importować pwd ani getpass.

Mam też wrażenie, że „domena / użytkownik” może być pomocna w niektórych aplikacjach w systemie Windows.

dylnmc
źródło
1
domain/usergroup/user
Windows
4
Moduł poleceń nie działa w systemie Windows. Jest to moduł specyficzny dla UNIX (patrz docs.python.org/2/library/commands.html ). Jest teraz przestarzałe i zamiast tego zaleca się podproces. user = subprocess.check_output("whoami").replace("\r\n", "")
ConnectedSystems
k; następnie użyj podprocesu ...
jeez
2 uwagi. polecenia.whoami spisały się świetnie, nawet w kontekście usługi działającej pod inną nazwą użytkownika. tzn. z chpst -u nobody python ./manage.py celerycam --pidfile=/var/run/celerycam/celerycam.pid nie mam nikogo . po drugie, user = subprocess.check_output("whoami").strip() jest bardziej przenośny niż wymienione zastępcze źródła linii. commandsvs subprocesswydaje się dziwaczne, ale brakuje poleceń w Pythonie 3.
JL Peyret
5

Napisałem moduł plx jakiś czas temu, aby uzyskać nazwę użytkownika w przenośny sposób w systemach Unix i Windows (między innymi): http://www.decalage.info/en/python/plx

Stosowanie:

import plx

username = plx.get_username()

(wymaga rozszerzeń win32 w systemie Windows)

kalkomania
źródło
4

Używając tylko standardowych bibliotek Pythona:

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

Działa w systemie Windows, Mac lub Linux

Alternatywnie możesz usunąć jedną linię za pomocą natychmiastowego wywołania:

from os import environ,getcwd
user = (lambda: environ["USERNAME"] if "C:" in getcwd() else environ["USER"])()
ThisGuyCantEven
źródło
1
getpass jest także standardową biblioteką
jodag
nie działa dla mnie w win10, python3.7.4. Chyba narzeka na to, że w zmiennych środowiska nie znaleziono „USER”. Wydaje mi się, że i tak getpass jest lepszym wyborem.
Rika
3

Możesz uzyskać bieżącą nazwę użytkownika w systemie Windows, przechodząc przez interfejs API systemu Windows, chociaż wywoływanie za pomocą FFI ctyp jest nieco kłopotliwe ( GetCurrentProcessOpenProcessTokenGetTokenInformationLookupAccountSid ).

Napisałem mały moduł, który może to zrobić prosto z Pythona, getuser.py . Stosowanie:

import getuser
print(getuser.lookup_username())

Działa zarówno w systemie Windows, jak i * nix (ten ostatni używa pwdmodułu zgodnie z opisem w innych odpowiedziach).

Michael Kropat
źródło