Help needed - function apparently global cannot be called.

Bruno Desthuilliers bruno.42.desthuilliers at websiteburo.invalid
Tue Sep 7 12:50:19 CEST 2010

Ian Hobson a écrit :
> Hi all you experts,
> This has me beat. Has anyone any ideas about what might be going wrong?
> This is code from within a windows service (hence no print statements - 
> no sys.stdout to print on!).
> I am trying to trace through to find where the code is not working. No 
> stdout so I have to log to a file.

Then you'd be better using the logging module from the stdlib. And FWIW, 
  you should try to make you code testable in a non-service context...

> I have the following code fragments.
> def log(message):
>     f = open('d:\logfile.txt','a')
>     f.write(message + "\n")
>     f.close()
> from DelNotePrinter import DelNotePrinter

The convention is to use all_lower_names for modules - having modules 
and classes with the same (case-sensitive) name can be very misleading.

> note the order of the above - log is defined before the import.

And ? Do you think it will affect the imported module in any way ? Like, 
say, magically "inject" your log function in the DelNotePrinter module ?-)

> Later in the  source

Where ?

> I have
>         log('disPrint is:'+disPrint)
>         log('count is:'+count)

Do yourself a favor and learn string formating...

>         log(repr(DelNotePrinter))
>         printer = DelNotePrinter(disPrint,int(count))

> The file cannot us log even though it is declared
> as global.

In Python, "global" means "module-level", and it's only necessary when 
you want to rebind a module-level name from within a function or method.

  The code is...
> # coding=utf8
> #    DelNotePrinter = code to print delivery notes
>   assorted imports removed for space reasons

Some of these imports surely explain why you don't just get a NameError 
when trying to call log() - wild guess : you have some "from xxx import 
*" statement that does import another callable named 'log'.

> class DelNotePrinter(object):
>     ''' Print Delivery Note on A5 in portrait '''
>     def __init__(self,printer,copies):
>         ''' create printer and painter '''
>         global font,sm,log
>         log('DelNotePrinter: starting')

>         self.printer = QPrinter(QPrinter.HighResolution)

If you want to access a name (function, class, whatever) defined in 
another module, you have to explicitely import it.

> The file the log writes contains..
> disPrint is:HP Deskjet 6940 series
> count is:1
> <class 'DelNotePrinter.DelNotePrinter'>
> The > is followed by a newline and end of file! Where is the 
> DelNotePrinter: starting message?

We can't tell - but you can get at least some hint, cf below

> If I replace the opening of __init__ with
>     global font,sm,log
>         f = open('d:\logfile.txt','a')
>         f.write('DelNotePrinter: starting' + "\n")
>         f.close()
>         self.printer = QPrinter(QPrinter.HighResolution)
> then the message IS written to the log file.

Obviously, yes. Now please add this to your code:

class DelNotePrinter(object):
     ''' Print Delivery Note on A5 in portrait '''
     def __init__(self,printer,copies):
         ''' create printer and painter '''
         global font,sm,log
         f = open('d:\logfile.txt','a')
         f.write('DelNotePrinter: starting' + "\n")

         # check what "log" is bound to in the currrent namespace
            "DelNotePrinter : log is '%s' from '%s'" % (
               log, log.__module__
         self.printer = QPrinter(QPrinter.HighResolution)

> I have read 
> very carefully and I still don't understand.

The statement definition makes no sense if you don't understand 
namespaces and bindings:

More information about the Python-list mailing list