PyMOTW: grp

grp – Unix Group Database

Purpose:Read group data from Unix group database.
Python Version:1.4 and later

The grp module can be used to read information about Unix groups from the group database (usually /etc/group). The read-only interface returns tuple-like objects with named attributes for the standard fields of a group record.


IndexAttributeMeaning
0gr_nameName
1gr_passwdPassword, if any (encrypted)
2gr_gidNumerical id (integer)
3gr_memNames of group members

The name and password values are both strings, the GID is an integer, and the members are reported as a list of strings.


Querying All Groups

Suppose you need to print a report of all of the “real” groups on a system, including their members (for our purposes, “real” is defined as having a name not starting with “_”). To load the entire password database, you would use getgrall(). The return value is a list with an undefined order, so you probably want to sort it before printing the report.

import grp
import operator

# Load all of the user data, sorted by username
all_groups = grp.getgrall()
interesting_groups = sorted((g
for g in all_groups
if not g.gr_name.startswith('_')),
key=operator.attrgetter('gr_name'))

# Find the longest length for the name
name_length = max(len(g.gr_name) for g in interesting_groups) + 1

# Print report headers
fmt = '%-*s %4s %10s %s'
print fmt % (name_length, 'Name',
'GID',
'Password',
'Members')
print '-' * name_length, '----', '-' * 10, '-' * 30

# Print the data
for g in interesting_groups:
print fmt % (name_length, g.gr_name,
g.gr_gid,
g.gr_passwd,
', '.join(g.gr_mem))
$ python grp_getgrall.py
Name GID Password Members
---------------------------------------- ---- ---------- ------------------------------
accessibility 90 *
admin 80 * root, dhellmann
authedusers 50
bin 7 *
certusers 29 * root, _jabber, _postfix, _cyrus, _calendar
com.apple.access_screensharing-disabled 101 dhellmann
consoleusers 53
daemon 1 * root
dhellmann 501
dialer 68 *
everyone 12
group 16
interactusers 51
kmem 2 * root
localaccounts 61
mail 6 *
netaccounts 62
netusers 52
network 69 *
nobody -2 *
nogroup -1 *
operator 5 * root
owner 10
postgres 401
procmod 9 * root
procview 8 * root
racemi 500 dhellmann
smmsp 25
staff 20 * root, test
sys 3 * root
tty 4 * root
utmp 45 *
wheel 0 * root


Group Memberships for a User

Another common task might be to print a list of all the groups for a given user:

import grp

username = 'dhellmann'
groups = [g.gr_name for g in grp.getgrall() if username in g.gr_mem]
print username, 'belongs to:', ', '.join(groups)
$ python grp_groups_for_user.py
dhellmann belongs to: _lpadmin, admin, com.apple.access_screensharing-disabled, racemi

Finding a Group By Name

As with pwd, it is also possible to query for information about a specific group, either by name or numeric id.

import grp

name = 'admin'
info = grp.getgrnam(name)
print 'Name :', info.gr_name
print 'GID :', info.gr_gid
print 'Password:', info.gr_passwd
print 'Members :', ', '.join(info.gr_mem)
$ python grp_getgrnam.py
Name : admin
GID : 80
Password: *
Members : root, dhellmann

Finding a Group by ID

To identify the group running the current process, combine getgrgid() with os.getgid().

import grp
import os

gid = os.getgid()
group_info = grp.getgrgid(gid)
print 'Currently running with GID=%s name=%s' % (gid, group_info.gr_name)
$ python grp_getgrgid_process.py
Currently running with GID=501 name=dhellmann

And to get the group name based on the permissions on a file, look up the group returned by os.stat().

import grp
import os
import sys

filename = 'grp_getgrgid_fileowner.py'
stat_info = os.stat(filename)
owner = grp.getgrgid(stat_info.st_gid).gr_name

print '%s is owned by %s (%s)' % (filename, owner, stat_info.st_gid)
$ python grp_getgrgid_fileowner.py
grp_getgrgid_fileowner.py is owned by dhellmann (501)

See also

grp
The standard library documentation for this module.
pwd
Read user data from the password database.
spwd
Read user data from the shadow password database.

PyMOTW Home

  • http://www.blogger.com/profile/00299003818364105534 rgz

    pretty good, I’ll remember grp next time I have to work with groups, thanks, now let the rant begin:

    Haven’t you noticed that:
    lambda x:x['gr_name']
    Is shorter than:
    import operator
    operator.attrgetter(‘gr_name’)
    ?

    I remember your post about operator, it is an inspiring module, but lambda makes it very redundant.

    Lambda also make map and filter mostly redundant. Ironically I made good use of reduce once:
    reduce(lambda x, y: x + y, collectedCards, [])
    doubly ironically operator.add *is* shorter in this case, but I’d have to import it, none of this would had been necessary if only sum supported lists of course.

  • Anonymous

    lambda ist slow as it is nothing more than a mere function call. operator is faster.

  • http://www.blogger.com/profile/01892352754222143463 Doug Hellmann

    @rgz – I chose to use operator instead of lambda because I’d already written a post about the operator module. I’m less interested in typing fewer characters than in making the code clear.

    I suspect Anonymous is correct about performance, but don’t have any numbers to back it up. In any case, the amount of data involved here is usually small enough that it wouldn’t be noticeable, so that wasn’t a primary consideration.