Weird import behavior

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Tommytrojan

    Weird import behavior

    Hi,

    I have been using Python for a while but today I came across a really
    strange behavior:

    While poking around in Queue.py due to problems with importing this
    module from a thread I got an error that a module that I imported on
    top of the file could not be accessed. I reduced the problem to this
    small script:

    import string
    import os

    class T:
    def __init__(self):
    try:
    print 'xxx nothing to do'
    except ImportError:
    print 'got an import error'
    import os as string

    print 'xxxx string module', string

    t=T()


    The import clause in the except statement (although never executed)
    removes the reference to the string module imported at the beginning of
    the script. Any idea why this is the case?

    Thanks,
    Tommy

  • Duncan Booth

    #2
    Re: Weird import behavior

    Tommytrojan wrote:
    [color=blue]
    > import string
    > import os
    >
    > class T:
    > def __init__(self):
    > try:
    > print 'xxx nothing to do'
    > except ImportError:
    > print 'got an import error'
    > import os as string
    >
    > print 'xxxx string module', string
    >
    > t=T()
    >
    >
    > The import clause in the except statement (although never executed)
    > removes the reference to the string module imported at the beginning of
    > the script. Any idea why this is the case?[/color]

    Quoting the error message would have made the answer instantly clear to
    everyone, including probably yourself:

    UnboundLocalErr or: local variable 'string' referenced before assignment

    Assigning to the variable 'string' anywhere in the function makes it a
    local variable throughout the function. Use 'global string' if you want the
    import to affect the global variable.

    Comment

    • Tommytrojan

      #3
      Re: Weird import behavior

      Duncan,

      thanks for your quick reply. I guess I should have included the output.
      I thought I was clear in the error description.
      The problem is that I never assign to 'string'. I only reference it (as
      the error message correctly states). If you comment out the import
      statement in the except clause the program runs fine. Now notice that
      the exception hander never gets executed! Any explanation?

      Comment

      • Duncan Booth

        #4
        Re: Weird import behavior

        Tommytrojan wrote:
        [color=blue]
        > Duncan,
        >
        > thanks for your quick reply. I guess I should have included the output.
        > I thought I was clear in the error description.
        > The problem is that I never assign to 'string'. I only reference it (as
        > the error message correctly states). If you comment out the import
        > statement in the except clause the program runs fine. Now notice that
        > the exception hander never gets executed! Any explanation?
        >[/color]
        You have an assignment to 'string' in the function (import, class and def
        statements are all equivalent to assignment statements so far as scoping
        is concerned). It doesn't matter whether or not the assignment gets
        executed: the compiler flags the variable as a local variable.

        See the Python FAQ, 1.2.2:

        1.2.2 What are the rules for local and global variables in Python?

        In Python, variables that are only referenced inside a function are
        implicitly global. If a variable is assigned a new value anywhere within
        the function's body, it's assumed to be a local. If a variable is ever
        assigned a new value inside the function, the variable is implicitly local,
        and you need to explicitly declare it as 'global'.

        Comment

        • Fredrik Lundh

          #5
          Re: Weird import behavior

          "Tommytroja n" wrote:
          [color=blue]
          > thanks for your quick reply. I guess I should have included the output.
          > I thought I was clear in the error description.
          > The problem is that I never assign to 'string'. I only reference it (as
          > the error message correctly states). If you comment out the import
          > statement in the except clause the program runs fine. Now notice that
          > the exception hander never gets executed! Any explanation?[/color]

          the language reference has the full story:



          "If a name is bound in a block, it is a local variable of that
          block." /.../

          "The following constructs bind names: formal parameters
          to functions, import statements, class and function definitions
          (these bind the class or function name in the defining block),
          and targets that are identifiers if occurring in an assignment,
          for loop header, or in the second position of an except
          clause header. The import statement of the form "from ...
          import *" binds all names defined in the imported module,
          except those beginning with an underscore. /.../

          A target occurring in a del statement is also considered bound
          for this purpose (though the actual semantics are to unbind
          the name). /.../

          If a name binding operation occurs anywhere within a code block,
          all uses of the name within the block are treated as references to
          the current block."

          </F>



          Comment

          • Tommytrojan

            #6
            Re: Weird import behavior

            Thanks for the clarification. I never ran into this before although I
            have been working with Python for over 8 years. Good to learn something
            new.

            Cheers,
            Thomas

            Comment

            Working...