468,512 Members | 1,606 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,512 developers. It's quick & easy.

Python equivalent for C module

I'd like to know if it's possible to code something in Python which
would be equivalent to the following C:

[Assume bool is typedef'd to int, and TRUE and FALSE are #defined to 1
and 0, respectively]

---- debug.c ----
#include <stdio.h>

bool DEBUG;

void dprint(char *msg)
{
if (DEBUG){
printf("DEBUG: %s", msg);
}
}

---- end of debug.c ----

The idea being that all modules of the program would "import" this
code via the header file:

---- debug.h ----
extern bool DEBUG;
void dprint(char *msg);
---- end of debug.h ----

I'm specifically trying to avoid having to create a debug object and
pass it around... All modules should have visibility into the state of
whether DEBUG is turned on or off, and be able to use dprint(). Can
Python do this?

I tried creating debug.py as such:

---- debug.py ----
DEBUG = True
def dprint(msg):
if DEBUG:
print("DEBUG: %s" % msg)
---- end ----

Then in the modules that wanted to use it, I did:

from debug import DEBUG, dprint

But I got some weird behavior. The imported copy of DEBUG is
read-only; if you update it, the name DEBUG points to a different
object which the other modules can't see. After doing some reading of
the docs, this behavior is explained and understood (though obviously
not what I want). It just occured to me that I might be able to get
around that by using a setter function in the module itself... I'll
try this later.

The other weird behavior was, once I changed the value of DEBUG,
dprint() started to behave oddly. No matter what I passed as an
argument (and no matter what I set the value of DEBUG to be), it
started printing the exact literal string:

DEBUG: %s

whenever it was called. It was as if the function couldn't see the
parameter msg, which was passed via the call. Most unexpected, and
definitely undesirable.

--
Derek D. Martin
http://www.pizzashack.org/
GPG Key ID: 0x81CFE75D
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.1 (GNU/Linux)

iD8DBQFI/L2HdjdlQoHP510RAhK6AJ4sD23vaAlBxaCYFGlS9g6Uhhd1FAC eJbkO
kIDJ86K7S2+B5m0uKKNoIlo=
=5Uek
-----END PGP SIGNATURE-----

Oct 20 '08 #1
8 1387
On Oct 20, 12:19*pm, Derek Martin <c...@pizzashack.orgwrote:
snip
>
I'm specifically trying to avoid having to create a debug object and
pass it around... All modules should have visibility into the state of
whether DEBUG is turned on or off, and be able to use dprint(). *Can
Python do this?

I tried creating debug.py as such:

---- debug.py ----
DEBUG = True
def dprint(msg):
* * if DEBUG:
* * * * print("DEBUG: %s" % msg)
---- end ----

Then in the modules that wanted to use it, I did:

from debug import DEBUG, dprint

But I got some weird behavior. *The imported copy of DEBUG is
read-only; if you update it, the name DEBUG points to a different
object which the other modules can't see. *After doing some reading of
the docs, this behavior is explained and understood (though obviously
not what I want). *It just occured to me that I might be able to get
around that by using a setter function in the module itself... I'll
try this later.

The other weird behavior was, once I changed the value of DEBUG,
dprint() started to behave oddly. *No matter what I passed as an
argument (and no matter what I set the value of DEBUG to be), it
started printing the exact literal string:

DEBUG: %s

whenever it was called. *It was as if the function couldn't see the
parameter msg, which was passed via the call. *Most unexpected, and
definitely undesirable.
It should work if you set the attribute of the module directly.

(untested)
import debug
debug.DEBUG= True
debug.DEBUG= False

Your idea of a module getter/setter should work too.

def set_debug( val ):
global DEBUG
DEBUG= val

Can't help with the other problem. Simplify a little with just
print( msg ).
Oct 20 '08 #2
Bruno Desthuilliers <bd*****************@free.quelquepart.frwrites:
STDOUT is for *normal* program outputs. Debug informations,
warnings, and all verbosity should go to STDERR.
Actually, stderr is for errors, by convention. It's rather impolite to
dump trivial debug info to stderr, which often "alerts" the user more
than stdout.
Also and FWIW, Python has a logging module in it's stdlib. Please
use it instead of any half-backed squared-wheel homegrown solution.
Unfortunately these square-wheeled homegrown solutions are easier to
grok than the standard logging module. It seems to target more
"serious" applications at the cost of feeling a bit too clunky for
quick hack jobs.
Oct 20 '08 #3
On Mon, Oct 20, 2008 at 07:29:16PM +0200, Bruno Desthuilliers wrote:
This should have been:

fprintf(STDERR, "DEBUG: %s", msg);
No, it shouldn't have. If I turn on debugging, I want the debug
messages to go to stdout, so that they can be captured along with the
output (of which there is almost none anyway) to clearly indicate when
they happened.
STDOUT is for *normal* program outputs. Debug informations, warnings,
and all verbosity should go to STDERR.
That's your opinion, and I disagree. Besides which, if you're running
a program in debug mode, you're DEBUGGING... "normal" does not apply.
You're being rather presumptuous... you don't even know how my program
is being used.
Then in the modules that wanted to use it, I did:

from debug import DEBUG, dprint
But I got some weird behavior. The imported copy

It's not a copy.
Actually, I'm pretty sure it is; i.e. there are two copies of the
name: one in the namespace of the module, and one in the namespace of
the file into which I imported it. At the time they are created, they
both point to the same object. Is that not the very definition of a
copy? The object itself may exist only in one place, but it has two
names; one in each namespace.
of DEBUG is
read-only;

It's not read-only.
The *object* very much is: it is immutable. The name of that object
is DEBUG, and thus DEBUG is read-only. You can make DEBUG point to a
different object by binding a different value to it, but if that value
is of an immutable type, it will still be a read-only object.

In the sentence I wrote, as well as in general, "DEBUG" actually
refers to two different things: the object bound to the name, and the
name itself. It's up to the reader to infer which sense is correct
given the thing being said about it. It just so happens that the
English sentence I wrote refers to both simultaneously.
Just use a fully qualified name, so you dont make DEBUG local:

import debug
print debug.DEBUG
debug.DEBUG = True
print debug.DEBUG
Right, several people have already pointed this out. Which leads me
to believe that the point of your reply was to berate me into
following your conventions, which I have no interest in doing, in part
because they are counterproductive to my goals, and in part because
they are counter to the way I've been programming for 25 years.
Fortunately, it's not your call how I write my code.
Now note that ALL_UPPER names are - by convention - considered
'constants'. If this is supposed to be altered, don't write it ALL_UPPER.
YOUR convention, not mine.
Also and FWIW, Python has a logging module in it's stdlib. Please use it
instead of any half-backed squared-wheel homegrown solution.
Note that the correct possessive form of "it" is "its" with no
apostrophe. This was the only thing of value which you contributed,
though really, using that is way overkill for my needs. If I've
written bad code, by all means, please correct it. If I've written
code in a style that you happen not to like, please feel free to keep
that to yourself.
My 2 cents
Must be Zimbabwe currency...

--
Derek D. Martin
http://www.pizzashack.org/
GPG Key ID: 0x81CFE75D
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.1 (GNU/Linux)

iD8DBQFI/POFdjdlQoHP510RAou7AJ9mo1mV0WV2Yj/4xuaB1X0NTfQv5gCfVUgU
ktwvJ4Gba271o10F0uitqjo=
=4hzz
-----END PGP SIGNATURE-----

Oct 20 '08 #4
On Mon, 20 Oct 2008 17:09:25 -0400, Derek Martin wrote:
On Mon, Oct 20, 2008 at 07:29:16PM +0200, Bruno Desthuilliers wrote:
>This should have been:

fprintf(STDERR, "DEBUG: %s", msg);

No, it shouldn't have. If I turn on debugging, I want the debug
messages to go to stdout, so that they can be captured along with the
output (of which there is almost none anyway) to clearly indicate when
they happened.
I agree with this: debugging messages aren't errors, and shouldn't go to
stderr.
[...]
>Then in the modules that wanted to use it, I did:

from debug import DEBUG, dprint
But I got some weird behavior. The imported copy

It's not a copy.

Actually, I'm pretty sure it is; i.e. there are two copies of the name:
one in the namespace of the module, and one in the namespace of the file
into which I imported it.
Names are not first class Python objects. You can't pass a name to a
function and say "do something to this *name*, not the object".

(Of course you can pass a string that happens to match the name to exec,
but that's not the same thing.)

If you dig around in globals() or locals(), you will find strings 'DEBUG'
and 'dprint', but they aren't "names". They're just the strings that
represents the names, and it turns out that CPython caches many (all?)
such strings which look like identifiers, so there probably is literally
one and only one string 'DEBUG' no matter how many times you import the
module.

All of this is just splitting hairs, because you don't really mean Python
is making a copy of the name 'DEBUG', but of the *data* that DEBUG refers
to, namely the object True. And it turns out that True is a singleton:
there is only ever one object True.

But even if DEBUG was set to some other value, say [1, 2, 3, 'x'], you'd
still be wrong, because Python promises never to copy objects unless you
explicitly tell it to. There are a number of ways to prove this, but
perhaps this is the simplest:

DEBUG = [True] # a mutable list

Now from your calling code, do this:

from module import DEBUG
DEBUG[0] = False # mutate the object, don't rebind the name

At the time they are created, they both point
to the same object. Is that not the very definition of a copy?
No. It would be a copy if they pointed to different objects, where one
object was a copy of the other.

The
object itself may exist only in one place,
which is exactly why there is no copy. It's the same object.

but it has two names; one in each namespace.
>of DEBUG is
read-only;

It's not read-only.

The *object* very much is: it is immutable.
So what? The *name* DEBUG is not read-only.

The name of that object is
DEBUG, and thus DEBUG is read-only.
But it clearly isn't read-only, because as you yourself point out:
You can make DEBUG point to a
different object by binding a different value to it

[...]
Right, several people have already pointed this out. Which leads me to
believe that the point of your reply was to berate me into following
your conventions, which I have no interest in doing, in part because
they are counterproductive to my goals, and in part because they are
counter to the way I've been programming for 25 years. Fortunately, it's
not your call how I write my code.
No, and it's not your call what advice people give you. If you refuse to
follow good Pythonic advice because you prefer the way you learned
programming a quarter century ago (before Python even existed), please go
right ahead, but don't be surprised if people consider you a lousy Python
programmer.

>Now note that ALL_UPPER names are - by convention - considered
'constants'. If this is supposed to be altered, don't write it
ALL_UPPER.

YOUR convention, not mine.
Actually it is a very common convention in Python circles. I often use it
myself. However it's not the only one, and from time to time I use
others. I would consider using DEBUG unusual, but not excessively so.

>Also and FWIW, Python has a logging module in it's stdlib. Please use
it instead of any half-backed squared-wheel homegrown solution.

Note that the correct possessive form of "it" is "its" with no
apostrophe. This was the only thing of value which you contributed,
though really, using that is way overkill for my needs. If I've written
bad code, by all means, please correct it. If I've written code in a
style that you happen not to like, please feel free to keep that to
yourself.
Deary deary me... you come along here, asking noob Python questions, and
then get shirty when people give you friendly and perfectly good answers.
Are you trying to ensure that the next question you ask remains
unanswered?


--
Steven
Oct 20 '08 #5
On Oct 20, 3:08*pm, u...@asus-190829777.TeleWell.gateway (Ville M.
Vainio) wrote:
Bruno Desthuilliers <bdesth.quelquech...@free.quelquepart.frwrites:
STDOUT is for *normal* program outputs. Debug informations,
warnings, and all verbosity should go to STDERR.

Actually, stderr is for errors, by convention. It's rather impolite to
dump trivial debug info to stderr, which often "alerts" the user more
than stdout.
snip

Indeed. Just dump to STDTRIVIAL.
Oct 21 '08 #6
On Mon, Oct 20, 2008 at 10:43:55PM +0000, Steven D'Aprano wrote:
All of this is just splitting hairs,
Indeed... :)
because you don't really mean Python is making a copy of the name
'DEBUG', but of the *data* that DEBUG refers to, namely the object
True.
Well, as long as we're having semantic discussions... If you reread
my post, it should be clear that what you wrote above can not possibly
be the case. If you recall, my intent was to make a copy of a means
of accessing the value known by the name "DEBUG" contained in the
debug module, which could be accessed from any module in the program.
Clearly the data itself *must not* be a copy, or else what I was
trying to do would never have worked. What I was refering to as a
copy was in fact essentially the name, or more accurately (as regards
my conception of purpose) a reference to the data.
The *object* very much is: it is immutable.

So what? The *name* DEBUG is not read-only.
You may have missed where I explained that the name refers to two
different things, and that I, speaking in loose terms, was refering to
both things simultaneously but in different contexts. I was speaking
loosely -- I was using "read-only" as a figure of speech of sorts, and
elaborated *correctly* what actually happens. Again, if you reread
my original post with that explanation in mind, I think you'll find
that this is the only sensible interpretation for what I wrote.
Actually it is a very common convention in Python circles. I often use it
myself. However it's not the only one, and from time to time I use
others. I would consider using DEBUG unusual, but not excessively so.
To be honest, same here. My post contained throw-away C code that I
typed up on the fly, and the same goes for the Python -- I simply
translated the C code literally, so to speak. As has been pointed out
in a different thread (by Bruno himself, if I'm not mistaken), the
code hastily posted here need not represent the code that one would
write in "real" programs. But I find it offensive that certain people
here can't resist lambasting some posters who have simple questions,
because the code they posted isn't up to their particular favorite
coding "standards" (i.e. conventions), and I will speak out about it,
especially when it's done to me. I didn't ask about coding
conventions, but Bruno's response was roughly 75% about how my code
sucks, and maybe 25% about answering my question. And what part did
answer my question was completely redundant. It was roughly 95% a
waste of time and energy for both him and me, though I did learn about
the logging module...
Deary deary me... you come along here, asking noob Python questions, and
then get shirty when people give you friendly and perfectly good answers.
Well, we disagree that the answer Bruno provided was either friendly
or perfectly good. I did receive perfectly good answers, and if you
read the whole thread, you saw me accept such answers graciously.
Bruno's answer smacked of a superiority and arrogance that is not
uncommon among certain frequent posters. He has no idea what my
program does, or what my real code looks like, but apparently deigns
himself the Code Police, and finds it necessary to punnish people for
posting code which does not conform to his idea of Programming Law.

I can't deny that I should have been able to answer my own question
with only a few more moments thought... Though I don't think it's
quite right to characterize questions about scope as "noob" questions.
I suspect actual noobs don't yet know enough to ask such questions.
Are you trying to ensure that the next question you ask remains
unanswered?
Not at all, just trying to preempt the pound of attitude that often
goes with the ounce of answers. But if the choice is between no
answer, and an answer that barely manages to avoid calling me an idiot
(especially over coding style), I'd rather have no answer.

--
Derek D. Martin
http://www.pizzashack.org/
GPG Key ID: 0x81CFE75D
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.1 (GNU/Linux)

iD8DBQFI/VrodjdlQoHP510RAlP0AKCVY28QZExTJ3+epEepD9k0UP13PwC cD0Jl
4HsvU97JMRcBpKuAOSoCCwQ=
=lHMm
-----END PGP SIGNATURE-----

Oct 21 '08 #7
On Oct 20, 9:08 pm, u...@asus-190829777.TeleWell.gateway (Ville M.
Vainio) wrote:
Unfortunately these square-wheeled homegrown solutions are easier to
grok than the standardloggingmodule. It seems to target more
"serious" applications at the cost of feeling a bit too clunky for
quick hack jobs.
I'm surprised to hear you say that. All you need is

import logging

logging.warning("Message with %s data", "variable") # or debug, info,
error

and I'd like to know what simpler interface you think would be better/
easier to grok for quick hack jobs.

Regards,

Vinay Sajip
Oct 21 '08 #8
Vinay Sajip <vi*********@yahoo.co.ukwrites:
import logging

logging.warning("Message with %s data", "variable") # or debug, info,
error

and I'd like to know what simpler interface you think would be better/
easier to grok for quick hack jobs.
It's not the logging itself that is a problem, it's setting up the
loggers that was nontrivial (back in the day I last tried it).

Some googling revealed what was my problem back in 2004:

http://coding.derkeiler.com/Archive/...4-10/3714.html

I do realize the technical problems of coming up with
one-size-fits-all solution for a problem domain like this.
Oct 21 '08 #9

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

54 posts views Thread by Brandon J. Van Every | last post: by
14 posts views Thread by David MacQuigg | last post: by
2 posts views Thread by ajikoe | last post: by
852 posts views Thread by Mark Tarver | last post: by
reply views Thread by NPC403 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.