2

I am looking to make a global function in python 3.3 like the print function. In particular we have embedded python in our own application and we want to expose a simple 'debug(value)' global function, available to any script. It is possible for us to do this by attaching the function to a module, however, for convenience it would be easier for it to be global like 'print(value)'.

How do you declare a global function that becomes available to any python file without imports, or is this a black box in python? Is it possible to do from the C side binding?

Trevor Sundberg
  • 1,584
  • 1
  • 14
  • 25
  • 2
    Is making this part of a module not working out for your situation? – summea Apr 02 '13 at 18:20
  • See this question http://stackoverflow.com/questions/4698493/can-i-add-custom-methods-attributes-to-built-in-python-types – wallacer Apr 02 '13 at 18:22
  • @Stephane For some reason I never found that in my searches, and I've been searching on google for over an hour about 'global functions' in python. Thanks – Trevor Sundberg Apr 02 '13 at 18:25
  • @Rovert, however abarnert answer is not available on the dupplicate question... so I 'm gonna try to revert my close vote, because his answer is of interest. – Stephane Rolland Apr 02 '13 at 18:27
  • That question seems to be able making a regular module-global function. And, not only that, that original question already did it properly, and the OP just didn't know how to read the error message. – abarnert Apr 02 '13 at 18:27
  • @StephaneRolland upon reading, the global function he's writing looks like its only global to a single file. The proposed 'builtins' solution seems like the best thus far. I'm currently testing it out. – Trevor Sundberg Apr 02 '13 at 18:32
  • @Rovert yes, that's why I do think abarnet's answer is of interest. I did learn something reading it :-) – Stephane Rolland Apr 02 '13 at 18:33
  • @JanneKarila: That question is specifically for 2.x, not 3.x, which is a bit different. On the other hand, the answer there does a better job than mine explaining you you don't want to do it. – abarnert Apr 02 '13 at 18:37
  • If @abarnert 's answer is useful it can be migrated to one of the other questions – N_A Apr 02 '13 at 18:44
  • This is not a dup of the first link. It may be a dup of the second, but as it stands, this is pretty misleading. – abarnert Apr 02 '13 at 19:37

1 Answers1

4

This is almost always a bad idea, but if you really want to do it…

If you print out or otherwise inspect the print function, you'll see it's in the module builtins. That's your clue. So, you can do this:

debugmodule.py:

import builtins
builtins.debug = debug

Now, after an import debugmodule, any other module can just call debug instead of debugmodule.debug.


Is it possible to do from the C side binding?

In CPython, C extension module can basically do the same thing that a pure Python module does. Or, even more simply, write a _debugmodule.so in C, then a debugmodule.py that imports it and copies debug into builtins.

If you're embedding CPython, you can do this just by injecting the function into the builtins module before starting the script/interactive shell/whatever, or at any later time.


While this definitely works, it's not entirely clear whether this is actually guaranteed to work. If you read the docs, it says:

As an implementation detail, most modules have the name __builtins__ made available as part of their globals. The value of __builtins__ is normally either this module or the value of this module’s __dict__ attribute. Since this is an implementation detail, it may not be used by alternate implementations of Python.

And, at least in CPython, it's actually that __builtins__ module or dict that gets searched as part of the lookup chain, not the builtins module. So, it might be possible that another implementation could look things up in __builtins__ like CPython does, but at the same time not make builtins (or user modifications to it) automatically available in __builtins__, in which case this wouldn't work. (Since CPython is the only 3.x implementation available so far, it's hard to speculate…)

If this doesn't work on some future Python 3.x implementation, the only option I can think of is to get your function injected into each module, instead of into builtins. You could do that with a PEP-302 import hook (which is a lot easier in 3.3 than it was when PEP 302 was written… read The import system for details).


In 2.x, instead of a module builtins that automatically injects things into a magic module __builtins__, there's just a magic module __builtin__ (notice the missing s). You may or may not have to import it (so you might as well, to be safe). And you may or may not be able to change it. But it works in (at least) CPython and PyPy.


So, what's the right way to do it? Simple: instead of import debugmodule, just from debugmodule import debug in all of your other modules. That way it ends up being a module-level global in every module that needs it.

abarnert
  • 354,177
  • 51
  • 601
  • 671