Hi Bruno,

Thanks for your quick response.  I still do not understand.

On 07/09/2010 11:50, Bruno Desthuilliers wrote:
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...
Thanks for the tip. "Batteries included" means there are so many batteries you miss some.

The Module I am trying to use works perfectly as a free standing routine.


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

<OT>
The convention is to use all_lower_names for modules - having modules and classes with the same (case-sensitive) name can be very misleading.
</OT>
The convention is a good one.

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 ?-)
Just that log is defined before the global log is encountered to that if the compiler needed to set up a link at compile time it was able to do so.



Later in the  source

Where ?

About 350 lines further down.
I have

        log('disPrint is:'+disPrint)
        log('count is:'+count)

Do yourself a favor and learn string formating...
Agreed. :) - These are debug statements to discover what is going on.

I have had so much trouble with problems NOT being reported, that I avoid anything that I am not 100% sure must work.


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


The DelNotePrinter.py 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.
Exactly! I want to bind the name log to the function I wrote.
So I carefully placed log in global scope and told the compiler that when I referred to log I meant the global one I wrote.
I expected that to bind log to the function I wrote.
The compiler did not complain it was undefined (which would have caused a trackback on the Event log).

But neither was the routine called.   :(

I still don't understand what is going wrong.

 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'.

I don't think so. The lines are

import sys
import datetime
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from DataBaseClass import DataBase

I know all PyQt classes begin with Q. Database I wrote, and it has no log in it.

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
        f.write(
           "DelNotePrinter : log is '%s' from '%s'" % (
              log, log.__module__
              ))
        f.close()
        self.printer = QPrinter(QPrinter.HighResolution)

I tried that (using copy/paste) and got no output! So I modified is slightly to

        global log
        f = open('d:\logfile.txt','a')
        f.write("test message\n")
        f.write(
           "DelNotePrinter : log is '%s' from '%s'" % (
              log, log.__module__
              ))
        f.close()
        self.printer = QPrinter(QPrinter.HighResolution)

I get my "test message" and then nothing. When I close the service, the next
log message comes from the closing code.

There are no errors reported, no messages, no Event log entries and nothing further happens. Its as if the thread died.

I have read http://docs.python.org/reference/simple_stmts.html#global very carefully and I still don't understand.

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

http://docs.python.org/reference/executionmodel.html#naming-and-binding

Thanks for the pointer. What a truly execrable piece of writing - full of over-long sentences and multiple subordinate clauses. It routinely uses terms before definition, and sometimes without definition. It is astonishingly bad.

The third sentence reads "Each occurrence of a name in the program text refers to the /binding/ of that name established in the innermost function block containing the use." What does that mean? It appears to mean that it is the assignment in the innermost function block that binds for all uses, not the first, not module blocks, not class blocks and not code blocks - but the innermost function block. That might be correct, but somehow I doubt it, for it would mean that earlier bindings are ignored or invalidated or not used or something - even if the inner block is not executed.

I am not stupid and English is my mother tongue, and I have read that page many times. The implications of the passage are still opaque to me.

How can I call a global function placed at the top of the source. Do I really have to move a 4 line function into its own file and import it again and again and again?

Regards

Ian
-- 
http://mail.python.org/mailman/listinfo/python-list

Reply via email to