Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unexecuted import in function causes UnboundLocalError #79250

Closed
jhewitt mannequin opened this issue Oct 25, 2018 · 9 comments
Closed

Unexecuted import in function causes UnboundLocalError #79250

jhewitt mannequin opened this issue Oct 25, 2018 · 9 comments
Labels
stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error

Comments

@jhewitt
Copy link
Mannequin

jhewitt mannequin commented Oct 25, 2018

BPO 35069
Nosy @stevendaprano, @matrixise

Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

Show more details

GitHub fields:

assignee = None
closed_at = <Date 2018-10-25.19:58:31.946>
created_at = <Date 2018-10-25.19:28:51.228>
labels = ['invalid', 'type-bug', 'library']
title = 'Unexecuted import in function causes UnboundLocalError'
updated_at = <Date 2018-10-25.22:55:21.804>
user = 'https://bugs.python.org/jhewitt'

bugs.python.org fields:

activity = <Date 2018-10-25.22:55:21.804>
actor = 'matrixise'
assignee = 'none'
closed = True
closed_date = <Date 2018-10-25.19:58:31.946>
closer = 'steven.daprano'
components = ['Library (Lib)']
creation = <Date 2018-10-25.19:28:51.228>
creator = 'jhewitt'
dependencies = []
files = []
hgrepos = []
issue_num = 35069
keywords = []
message_count = 9.0
messages = ['328470', '328471', '328472', '328475', '328478', '328481', '328487', '328489', '328506']
nosy_count = 3.0
nosy_names = ['steven.daprano', 'matrixise', 'jhewitt']
pr_nums = []
priority = 'normal'
resolution = 'not a bug'
stage = 'resolved'
status = 'closed'
superseder = None
type = 'behavior'
url = 'https://bugs.python.org/issue35069'
versions = ['Python 3.6']

@jhewitt
Copy link
Mannequin Author

jhewitt mannequin commented Oct 25, 2018

Having 'import logging.config' in an if statement in a function causes a namespace issue, despite the fact that the import is not reached.

Example code:

---
#!/usr/bin/env python3

# Test weird import bug

import logging


config = {}
config['log'] = {}
config['log']['log_type'] = 'file'
config['log']['log_file'] = './log'
config['log']['config'] = { 'version' : 1 }


def do_config_logging():
    if config['log']['log_type'] == 'from_config':
        import logging.config
        logging.config.dictConfig(config['log']['config'])
    elif config['log']['log_type'] == 'file':
        logging.basicConfig(filename=config['log']['log_file'])
        logging.info("start logging")


if __name__ == "__main__":
    do_config_logging()

This results in:

Traceback (most recent call last):
  File "./bug.py", line 25, in <module>
    do_config_logging()
  File "./bug.py", line 20, in do_config_logging
    logging.basicConfig(filename=config['log']['log_file'])
UnboundLocalError: local variable 'logging' referenced before assignment

Notes:

This was run on Ubuntu Linux 18.04 Intel 64-bit, Python version 3.6.6

The problem does not occur if the branch is actually taken, and it does not occur if the 'if' statement is not in a function. It also does not occur if 'logging.config' is imported as some other name, eg. 'configlogging'.

virtualenv is installed (via the distribution package) but not in use in the test case.

@jhewitt jhewitt mannequin added stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error labels Oct 25, 2018
@matrixise
Copy link
Member

Could you share a pastebin? Thank you

Le 25 oct. 2018 à 21:28, James Hewitt <report@bugs.python.org> a écrit :

New submission from James Hewitt <jgh@caurinus.com>:

Having 'import logging.config' in an if statement in a function causes a namespace issue, despite the fact that the import is not reached.

Example code:

---
#!/usr/bin/env python3

Test weird import bug

import logging

config = {}
config['log'] = {}
config['log']['log_type'] = 'file'
config['log']['log_file'] = './log'
config['log']['config'] = { 'version' : 1 }

def do_config_logging():
if config['log']['log_type'] == 'from_config':
import logging.config
logging.config.dictConfig(config['log']['config'])
elif config['log']['log_type'] == 'file':
logging.basicConfig(filename=config['log']['log_file'])
logging.info("start logging")

if __name__ == "__main__":
do_config_logging()

---

> 
> 
> This results in:
> 
> Traceback (most recent call last):
>  File "./bug.py", line 25, in <module>
>    do_config_logging()
>  File "./bug.py", line 20, in do_config_logging
>    logging.basicConfig(filename=config['log']['log_file'])
> UnboundLocalError: local variable 'logging' referenced before assignment
> 
> 
> Notes:
> 
> This was run on Ubuntu Linux 18.04 Intel 64-bit, Python version 3.6.6
> 
> The problem does not occur if the branch is actually taken, and it does not occur if the 'if' statement is not in a function.  It also does not occur if 'logging.config' is imported as some other name, eg. 'configlogging'.
> 
> virtualenv is installed (via the distribution package) but not in use in the test case.
> 
> 

components: Library (Lib)
messages: 328470
nosy: jhewitt
priority: normal
severity: normal
status: open
title: Unexecuted import in function causes UnboundLocalError
type: behavior
versions: Python 3.6


Python tracker <report@bugs.python.org>
<https://bugs.python.org/issue35069\>



New-bugs-announce mailing list
New-bugs-announce@python.org
https://mail.python.org/mailman/listinfo/new-bugs-announce

@jhewitt
Copy link
Mannequin Author

jhewitt mannequin commented Oct 25, 2018

Sure, it's at https://pastebin.com/L1RMPD7K

-James

On 10/25/2018 12:30 PM, Stéphane Wirtel wrote:

Stéphane Wirtel <stephane@wirtel.be> added the comment:

Could you share a pastebin? Thank you

> Le 25 oct. 2018 à 21:28, James Hewitt <report@bugs.python.org> a écrit :
>
>
> New submission from James Hewitt <jgh@caurinus.com>:
>
> Having 'import logging.config' in an if statement in a function causes a namespace issue, despite the fact that the import is not reached.
>
> Example code:
>
> ---
> #!/usr/bin/env python3
>
> # Test weird import bug
>
> import logging
>
>
> config = {}
> config['log'] = {}
> config['log']['log_type'] = 'file'
> config['log']['log_file'] = './log'
> config['log']['config'] = { 'version' : 1 }
>
>
> def do_config_logging():
> if config['log']['log_type'] == 'from_config':
> import logging.config
> logging.config.dictConfig(config['log']['config'])
> elif config['log']['log_type'] == 'file':
> logging.basicConfig(filename=config['log']['log_file'])
> logging.info("start logging")
>
>
> if __name__ == "__main__":
> do_config_logging()
>
> ---

>>
>>
>> This results in:
>>
>> Traceback (most recent call last):
>>   File "./bug.py", line 25, in <module>
>>     do_config_logging()
>>   File "./bug.py", line 20, in do_config_logging
>>     logging.basicConfig(filename=config['log']['log_file'])
>> UnboundLocalError: local variable 'logging' referenced before assignment
>>
>>
>> Notes:
>>
>> This was run on Ubuntu Linux 18.04 Intel 64-bit, Python version 3.6.6
>>
>> The problem does not occur if the branch is actually taken, and it does not occur if the 'if' statement is not in a function.  It also does not occur if 'logging.config' is imported as some other name, eg. 'configlogging'.
>>
>> virtualenv is installed (via the distribution package) but not in use in the test case.
>>
>> 

> components: Library (Lib)
> messages: 328470
> nosy: jhewitt
> priority: normal
> severity: normal
> status: open
> title: Unexecuted import in function causes UnboundLocalError
> type: behavior
> versions: Python 3.6
>
> _______________________________________
> Python tracker <report@bugs.python.org>
> <https://bugs.python.org/issue35069\>
> _______________________________________
> _______________________________________________
> New-bugs-announce mailing list
> New-bugs-announce@python.org
> https://mail.python.org/mailman/listinfo/new-bugs-announce

----------
nosy: +matrixise


Python tracker <report@bugs.python.org>
<https://bugs.python.org/issue35069\>


@stevendaprano
Copy link
Member

This is expected behaviour: import is a form of assignment.

"import logging", like "logging = 1", tells the compiler to treat logging as a local variable (unless you declare logging as global). As the exception says, you are trying to access the logging local variable before it has been assigned to.

You can (and should!) give a SHORT and SIMPLE demonstration, without any excess and irrelevant code:

py> def demo():
...     if False:
...             import logging
...     logging
...
py> demo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in demo
UnboundLocalError: local variable 'logging' referenced before assignment

So this is expected behaviour.

@stevendaprano
Copy link
Member

Stéphane, I'm curious why you asked for a pastebin when James already provided the code right here in the tracker? (Your email even included a copy of that code.) Why split the information into another website?

@jhewitt
Copy link
Mannequin Author

jhewitt mannequin commented Oct 25, 2018

I don't quite follow... the 'import logging.config' statement should
never be executed, and if it is commented out the program works fine as
written. It's as if the mere presence of the statement in the code
causes 'logging' to be shadowed inside the function.

-James

On 10/25/2018 12:58 PM, Steven D'Aprano wrote:
> 
> Steven D'Aprano <steve+python@pearwood.info> added the comment:
> 
> This is expected behaviour: import is a form of assignment.
> 
> "import logging", like "logging = 1", tells the compiler to treat logging as a local variable (unless you declare logging as global). As the exception says, you are trying to access the logging local variable before it has been assigned to.
> 
> You can (and should!) give a SHORT and SIMPLE demonstration, without any excess and irrelevant code:
> 
> py> def demo():
> ...     if False:
> ...             import logging
> ...     logging
> ...
> py> demo()
> Traceback (most recent call last):
>    File "<stdin>", line 1, in <module>
>    File "<stdin>", line 4, in demo
> UnboundLocalError: local variable 'logging' referenced before assignment
> 
> So this is expected behaviour.
> 
> 

nosy: +steven.daprano
resolution: -> not a bug
stage: -> resolved
status: open -> closed


Python tracker <report@bugs.python.org>
<https://bugs.python.org/issue35069\>


@stevendaprano
Copy link
Member

Yes, that's exactly right. That's how local variables work in Python:

x = 999  # global x
def demo():
   if False:
       x = 1
   x  # local x has no value

does the same thing. This is standard, documented behaviour, regardless
of which kind of assignment statement you use.

@jhewitt
Copy link
Mannequin Author

jhewitt mannequin commented Oct 25, 2018

So just the fact that somewhere in the function a name is referenced,
even if that code isn't actually executed, is enough to change the local
namespace. I think I knew that, but didn't know that's what it meant :)

I guess the moral is, pay attention to scope when importing submodules
dynamically.

Thanks for looking at this, sorry it wasn't a bit more interesting :)

-James

On 10/25/2018 01:32 PM, Steven D'Aprano wrote:

Steven D'Aprano <steve+python@pearwood.info> added the comment:

Yes, that's exactly right. That's how local variables work in Python:

x = 999 # global x
def demo():
if False:
x = 1
x # local x has no value

does the same thing. This is standard, documented behaviour, regardless
of which kind of assignment statement you use.

----------


Python tracker <report@bugs.python.org>
<https://bugs.python.org/issue35069\>


@matrixise
Copy link
Member

Hi Steven,

Sure, I am going to explain, I was at the social event of PyCon Germany without my laptop and the code was not really clear on my smartphone. I wanted to know if there was an indentation issue.

It's also the reason for my big reply with the initial email because I have replied on my phone.

But after that, you have replied.

I am really sorry for the inconvenience.

Thank you

@ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

2 participants