Macros in Python?

Ben Hutchings do-not-spam-ben.hutchings at businesswebsoftware.com
Thu Apr 10 16:31:21 CEST 2003


In article <b71qde$q71$07$1 at news.t-online.com>, Dominic wrote:
> 
> 
> (defmacro with-root-privs (() &body body)
>    (let ((oldidsym (gensym)))
>      `(let ((,oldidsym (geteuid)))
>         (seteuid 0)
>         (unwind-protect
> 	   (progn , at body)
> 	 (seteuid ,oldidsym)))))
> 
> Is there an easy way to produce similar code
> in Python which gurantees that certain things
> happen around some code? (Maybe by using
> generators?)
> 
> The normal approach would be to enclose everything
> with try: finally: but this would scatter the
> code all over.
> 
> Is something like this feasible?
> 
> def server(a,b):
>    if cond:
>        ...
>    else:
>      With_Root_Privs:
>         if x in user:
>            active.append(x)
>           (...)

Python has nothing like Lisp macros, but you can generically wrap
function calls by accepting and passing on arbitrary arguments with
the * and ** operators:

    def with_root_privs(func, *args, **kwargs):
        save_euid = os.geteuid()
        os.seteuid(0)
        try:
            func(*args, **kwargs)
        finally:
            os.seteuid(save_euid)

You can use the above like this:

    def activate_user(x):
        if x in user:
            active.append(x)
        ...
    with_root_privs(activate_user, x)

Alternatively, you can curry the above function:

    def with_root_privs(func):
        def call(func, *args, **kwargs):
            save_euid = os.geteuid()
            os.seteuid(0)
            try:
                func(*args, **kwargs)
            finally:
                os.seteuid(save_euid)
        return lambda *args, **kwargs: call(func, *args, **kwargs)

You can then write something like the following:

    def activate_user(x):
        if x in user:
            active.append(x)
        ...
    activate_user = with_root_privs(activate_user)
    ...
    activate_user(x)




More information about the Python-list mailing list