Python: How to get group ids of one username (like id -Gn )

Question:

getpwname can only get the gid of a username.

import pwd
myGroupId = pwd.getpwnam(username).pw_gid

getgroups can only get groups of the script user.

import os
myGroupIds = os.getgroups()

How can I get all groups of one arbitrary username, like the id -Gn command?

id -Gn `whoami`
Asked By: Ade YU

||

Answers:

The following works assuming you are only interested in local users only, it will not work for things such as sssd backed by a catalog server (for instance, ldap).

#!/usr/bin/env python

import grp, pwd 

user = "myname"
groups = [g.gr_name for g in grp.getgrall() if user in g.gr_mem]
gid = pwd.getpwnam(user).pw_gid
groups.append(grp.getgrgid(gid).gr_name)
print groups
Answered By: Gareth A. Lloyd

The result of id -Gn when the user belongs to one or more groups in which several group names map to the same gid might not be the same as the posted answer. For instance if /etc/groups is similar to this:

 % ypcat group | grep mygroup 
 mygroup:*:66485:user1,user2,user3,...
 mygroup1:*:66485:user101,user102,user103,...
 mygroup2:*:66485:user201,user202,user203,...
 ...

And if the user is not listed in mygroup but in mygroup<n>, id -Gn returns mygroup but the posted answer returns mygroup<n>.

It seems that in my environment, because UNIX groups can have hundreds or thousands of users, this is a common group management policy, although I don’t know exactly what is the user limit per group and why id -Gn always returns mygroup.

Nevertheless, with the code below I got a match with id -Gn:

import pwd, grp    

def getgroups(user):
    gids = [g.gr_gid for g in grp.getgrall() if user in g.gr_mem]
    gid = pwd.getpwnam(user).pw_gid
    gids.append(grp.getgrgid(gid).gr_gid)
    return [grp.getgrgid(gid).gr_name for gid in gids]
Answered By: jserras

If you want the current user’s groups.

import os, grp
[grp.getgrgid(g).gr_name for g in os.getgroups()]

os.getgroups() returns the list of gids of the current user.

grp.getgrgid(g) returns details about a group

Answered By: cs_alumnus

The only way I found to make this work correctly when having users non local to the system (e.g. ldap, sssd+ldap, freeIPA) without calling id in a subprocess is by calling the getgrouplist c function (which is called by id eventually after going trough some abstractions):

#!/usr/bin/python

import grp, pwd, os
from ctypes import *
from ctypes.util import find_library

libc = cdll.LoadLibrary(find_library('libc'))

getgrouplist = libc.getgrouplist
# 50 groups should be enough, if not, we'll repeat the request with the correct nr bellow
ngroups = 50
getgrouplist.argtypes = [c_char_p, c_uint, POINTER(c_uint * ngroups), POINTER(c_int)]
getgrouplist.restype = c_int32

grouplist = (c_uint * ngroups)()
ngrouplist = c_int(ngroups)

user = pwd.getpwuid(2540485)

ct = getgrouplist(bytes(user.pw_name, 'UTF-8'), user.pw_gid, byref(grouplist), byref(ngrouplist))

# if 50 groups was not enough this will be -1, try again
# luckily the last call put the correct number of groups in ngrouplist
if ct < 0:
    getgrouplist.argtypes = [c_char_p, c_uint, POINTER(c_uint *int(ngrouplist.value)), POINTER(c_int)]
    grouplist = (c_uint * int(ngrouplist.value))()
    ct = getgrouplist(user.pw_name, user.pw_gid, byref(grouplist), byref(ngrouplist))

for i in range(0, ct):
    gid = grouplist[i]
    print(grp.getgrgid(gid).gr_name)
Answered By: Jens Timmerman

Since Python 3.3:

import os
import pwd

uid = os.getuid()
user = pwd.getpwuid(uid)
gl = os.getgrouplist(user.pw_name, user.pw_gid)
print(gl)
Answered By: gerardw
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.