是否有一种可移植的方式来获取 Python 中的当前用户名?

Posted

技术标签:

【中文标题】是否有一种可移植的方式来获取 Python 中的当前用户名?【英文标题】:Is there a portable way to get the current username in Python? 【发布时间】:2010-10-24 22:21:49 【问题描述】:

是否有一种可移植的方式在 Python 中获取当前用户的用户名(即至少在 Linux 和 Windows 下都可以使用的方式)。它会像os.getuid

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

我用谷歌搜索了一下,很惊讶没有找到明确的答案(尽管也许我只是在谷歌上搜索得不好)。 pwd 模块提供了一种相对简单的方法来实现这一点,比如在 Linux 下,但它在 Windows 上不存在。一些搜索结果表明,在某些情况下(例如,作为 Windows 服务运行),在 Windows 下获取用户名可能会很复杂,尽管我尚未对此进行验证。

【问题讨论】:

它在我的 Linux 机器上不起作用! import pwd, os; print pwd.getpwuid(os.getuid()).pw_gecosimport pwd, os; print pwd.getpwuid(os.getuid()).pw_name getusername() 不是 os Python 模块中的有效方法:docs.python.org/2.7/library/os.html @MattBruzek 这就是 OP 的重点。他在想象如果存在这样的函数,如何调用它。 “用户名”甚至不是一个可移植的概念。考虑一下 microPython——如果你直接在硬件上运行,就没有这样的东西。 【参考方案1】:

以上都不适用于我的情况(向下滚动到实际解决方案)。 我在所有解决方案中遇到的问题是使用sudo 运行命令时用户名错误:

psutilsoulution:
$ 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解决方案:
$ 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 解决方案:
$ 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 工作方式有点不同,但仍然是错误的:
$ 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 给出相同的结果:
$ 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!

sudo python3 情况下切换SUDO_USERUSER 会产生错误的结果。

实际解决方案(非便携式)

解决方案有点棘手,依赖于默认的根主目录位置,但适用于所有情况:

$ 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!

【讨论】:

这是一个非常不同的问题的答案 但对此表示感谢 - 处理 sudo 问题,对于那些从此处引导的谷歌搜索中寻找答案的人来说,这是一个非常不同的问题。也许只是一个有点不同的问题。 sudo 升级,因此 root 实际上是用户。如果您希望能够定义自己的用户,我建议您创建一个 -u/--user 标志,以便您可以执行 sudo ./foo.py -u myUser 之类的操作 正如其他人所说,您得到的结果没有错。命令 is 以 root 身份运行,用于所有意图和目的。这可能对某人有用,但它不是 OP 问题的答案。【参考方案2】:

psutil 提供了一种不使用环境变量的可移植方式,例如getpass 解决方案。它不太容易出现安全问题,并且可能是目前公认的答案。

import psutil

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

在底层,它结合了基于 getpwuid 的 unix 方法和 GetTokenInformation 方法用于 Windows。

【讨论】:

是否有一个函数可以在没有域的情况下获取它,还是我将它拆分到 / 上?【参考方案3】:

仅使用标准 python 库:

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

适用于 Windows(如果您在驱动器 C 上)、Mac 或 Linux

或者,您可以立即调用删除一行:

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

【讨论】:

getpass 也是一个标准库 在 win10、python3.7.4 中对我不起作用。我猜它抱怨在环境变量中找不到“用户”。无论如何,我想 getpass 是一个更好的选择。 唯一会导致这种情况的是,如果您从 C: 以外的驱动器运行它。这是它使用USER 键而不是USERNAME 的唯一原因。这实际上只是一个 if/else ......它所做的只是使用 USERNAME 如果有一个 C: 驱动器 else USER 这只是一个 hacky 解决方案,如果您当前的工作目录在另一个驱动器上,它将中断。您的回答并没有真正比其他人提供好处。即使您想这样做,也有更好的方法来检查平台,但通常最好从一开始就使用可移植的东西。【参考方案4】:

至少对于 UNIX,这是可行的……

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

编辑: 我刚刚查了一下,这适用于 Windows 和 UNIX:

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

在 UNIX 上,它返回您的用户名,但在 Windows 上,它返回您的用户组、斜杠、您的用户名。

--

I.E.

UNIX 返回:“用户名”

Windows 返回:“域/用户名”

--

这很有趣,但可能并不理想,除非你无论如何都在终端中做某事......在这种情况下,你可能会使用 os.system 开始。例如,不久前我需要将我的用户添加到一个组中,所以我做了(这是在 Linux 中,请注意)

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"

我觉得这更容易阅读并且您不必导入 pwd 或 getpass。

我也觉得拥有“域/用户”可能对 Windows 中的某些应用程序有所帮​​助。

【讨论】:

Windows 返回 domain/user 而不是 group/user 命令模块在 Windows 上不起作用。这是一个 UNIX 特定的模块(请参阅docs.python.org/2/library/commands.html)。它现在已被弃用,而是推荐使用 subprocess。 user = subprocess.check_output("whoami").replace("\r\n", "") 2 条评论。 commands.whoami 做得很好,即使在以不同用户名运行的服务的上下文中也是如此。即chpst -u nobody python ./manage.py celerycam --pidfile=/var/run/celerycam/celerycam.pid 我得到了 nobody。其次,user = subprocess.check_output("whoami").strip() 比上面的替换换行符更便携。 commands vs subprocess 似乎很挑剔,但 python 3 中缺少命令。 -1 用于使用不安全的方法,至少你应该使用subprocess,但是无论如何为此生成一个单独的进程是过度的。【参考方案5】:

这些可能有效。我不知道它们在作为服务运行时的行为。它们不可移植,但这就是 os.nameifstatements 的用途。

win32api.GetUserName()

win32api.GetUserNameEx(...) 

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

【讨论】:

这个答案至少和(无用的)25 票赞成的 unix-only 答案一样有用。 >“至少同样有用”同意。大概正确的答案是两者的结合。 如果您在 Windows 上被困在 python 2 上,这是唯一安全的方法。在你的 python 命令之前运行SET USERNAME=FAKE 可以欺骗所有其他方法【参考方案6】:

你可能会使用:

os.environ.get('USERNAME')

os.environ.get('USER')

但这并不安全,因为可以更改环境变量。

【讨论】:

os.getenv(...) 已弃用,取而代之的是 os.environ[...] 不应该是USER而不是USERNAME吗? @MikeGraham os.getenv 似乎没有被弃用..? 是的,正是 USER vs USERNAME 正是不可移植的,所以它没有提供正确的答案。 USERNAME 适用于 Windows,USER 适用于 Linux【参考方案7】:

看getpass模块

import getpass
getpass.getuser()
'kostya'

可用性:Unix、Windows


附言根据下面的评论“此函数查看各种环境变量的值以确定用户名。因此,不应依赖此函数用于访问控制目的(或可能任何其他目的,因为它允许任何用户模拟任何其他)。"

【讨论】:

getpass.getuser() 没有任何问题,因为它没有声称对用户进行身份验证。该函数的目的是在不直接询问用户的情况下确定用户声称自己是谁。 如果你做了 su. $ echo $USER hithwen $ su julia 密码:$ echo $USER julia $ python >>> import getpass >>> getpass.getuser() 'hithwen' @GregHewgill 提出了一个很好的观点,但确实,像这样以简单的未经身份验证的方式找出用户名确实有一些应用程序。我当前的用例:用用户名标记一些共享测试资源,以便以后清理。 (所以更容易弄清楚谁的烂摊子。) 我同意@GregHewgill 的访问控制目的,但完全不同意“任何其他目的”——这就像说“不要在 shell 脚本中使用 $USER”。关于访问控制的要点很重要,但还有 大量 不涉及身份验证的其他用途。 @hithwen 按预期工作。这取决于您向su 提供的参数。也许你想使用su - julia【参考方案8】:

对我来说,使用os 模块看起来最适合可移植性:在 Linux 和 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]           

输出:

窗户:

用户的主目录:C:\Users\myuser

用户名:我的用户

Linux:

用户的主目录:/root

用户名:root

无需安装任何模块或扩展。

【讨论】:

这个解决方案很聪明,但做了一些并不总是正确的假设。没有要求用户名出现在 Linux 上的 homedir 路径中的约束。大多数情况下恰好是这种情况,但是系统管理员可以将用户的主目录设置为他们想要的任何内容。 设置 HOME 变量会破坏这一点。【参考方案9】:

如果你需要这个来获取用户的主目录,下面可以被认为是可移植的(至少是 win32 和 linux),是标准库的一部分。

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

您也可以解析此类字符串以仅获取最后一个路径组件(即用户名)。

见:os.path.expanduser

【讨论】:

某人的主目录并不总是反映他们的用户名。 不幸的是,如果您在 Windows 中设置 HOME 变量,这将返回该值。【参考方案10】:

您可以通过 Windows API 获取 Windows 上的当前用户名,尽管通过 ctypes FFI 调用有点麻烦(GetCurrentProcess → OpenProcessToken → GetTokenInformation → LookupAccountSid)。

我编写了一个小模块,可以直接从 Python 中执行此操作,getuser.py。用法:

import getuser
print(getuser.lookup_username())

它适用于 Windows 和 *nix(后者使用 pwd 模块,如其他答案中所述)。

【讨论】:

【参考方案11】:

结合pwdgetpass 方法,基于其他答案:

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()

【讨论】:

【参考方案12】:

最好的办法是将os.getuid()pwd.getpwuid() 结合起来:

import os
import pwd

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

有关详细信息,请参阅 pwd 文档:

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

【讨论】:

或者(读起来稍微好一点):pwd.getpwuid(os.getuid()).pw_name. 它在 Windows 上的作用是什么?也许可以尝试一下,如果失败了,就回退到糟糕的“getpass/env var”方法。 如果您需要在登录和未登录的情况下获取用户名,这是正确的方法。 @JonathanHartley: ImportError: No module named pwd 此方法在类 unix 系统上很多优于 Konstantin Tenzin 的答案,因为它正确处理了 sudo 案例。 (我知道 OP 没有要求类似 unix 的系统。)【参考方案13】:

我前段时间编写了 plx 模块,以在 Unix 和 Windows 上以可移植的方式获取用户名(除其他外): http://www.decalage.info/en/python/plx

用法:

import plx

username = plx.get_username()

(在 Windows 上需要 win32 扩展)

【讨论】:

【参考方案14】:

你也可以使用:

 os.getlogin()

【讨论】:

在 linux 上,getlogin() 返回“进程控制终端上登录的用户”的名称。因此,当没有控制终端时,例如在 mod_python 应用程序中,它会失败。 如果你使用了su,那么这将不会返回当前用户,而是最初登录的用户。 确实适用于 windows...Python 3.4.1 (v3.4.1:c0e311e010fc, May 18 2014, 10:38:22) [MSC v.1600 32 bit (Intel)] on win32 Type “帮助”、“版权”、“学分”或“许可”以获取更多信息。 >>> 导入操作系统; os.getlogin() 'jrb' 它仅适用于 Python 3.x 的 Windows。 谢谢。登录用户不是发帖人要求的,但正是我要找的。​​span>

以上是关于是否有一种可移植的方式来获取 Python 中的当前用户名?的主要内容,如果未能解决你的问题,请参考以下文章

标准 C++ 中是不是有一种可移植的方式来检索主机名?

是否有一种可移植的方式在 Makefile 中制作可移植的可选依赖项?

是否有一种可移植的(C++ 标准)方法来计算前一个对齐的指针?

有没有一种可移植的方式来用 Qt 给线程名称?

测试 Python 中是不是存在可执行文件?

有没有一种可移植的方法来设置flock() 的超时时间?