Paul
Paul

Reputation: 5974

Unbound local variable error when importing signal?

I am importing signal at the beginning of my file. I then wish to use this in a function like so:

 os.kill(pid, signal.SIGKILL)

I get an error:

UnboundLocalError: local variable 'signal' referenced before assignment.

If I instead import signal inside the function I get no such problem, why is this happening?

EDIT: example code

import signal
def func():
    if args.kill: # Never triggered
        import signal
        os.kill(int(args.pid), signal.SIGKILL)
    elif args.name:
        os.kill(int(args.pid), signal.SIGKILL)

Upvotes: 2

Views: 605

Answers (2)

Martijn Pieters
Martijn Pieters

Reputation: 1121814

Importing a name in a function is also an assignment; essentially your sample could be further reduced to this:

def function(arg1, arg2):
    if False:
        import signal

    os.kill(pid, signal.SIGKILL)

This makes signal a local variable in the function, and Python won't look for the global name.

The import signal line makes signal a local name, but because the line is never executed, signal is never bound and the exception is thrown.

Remove all import signal lines from the function, or move it out of the conditional to be imported unconditionally (and thus always bind signal).

Upvotes: 3

glglgl
glglgl

Reputation: 91017

Your second

import signal

in the function is the problem. Omit it.

It is just a local assignment as anything else: the module object will be assigned to the local name signal.

You can have it twice in a function - it is then local twice and the second import will do nothing, or you can it have once at the top of the function, but you cannot have it once buried deeply inside and only executed sometimes.

In your case, the error will occur if not args.kill. Then the assignment will not happen, but the local name doesn't cease to exist.

Compare this to

import signal as global_signal
signal = global_signal
def func():
    if args.kill: # Never triggered
        signal = global_signal
        os.kill(int(args.pid), signal.SIGKILL)
    elif args.name:
        os.kill(int(args.pid), signal.SIGKILL)
  • it is essentially the same, but with additional identifiers.

Upvotes: 2

Related Questions