UnboundLocalError: local variable .. referenced before assignment - python

I am starting with python. I am trying a very simple class-structure, but i get an error.
This is my script:
class controller:
def initLocal(self):
path = input('path:')
local = local()
local.path = path
return local
class location:
pass
class local(location):
path = None
controller = controller()
local = controller.initLocal()
And this is the result i get in the console:
path:a
Traceback (most recent call last):
File "path\to\test.py", line 21, in <module>
local = controller.initLocal();
File "path\to\test.py", line 5, in initLocal
local = local();
UnboundLocalError: local variable 'local' referenced before assignment
I searched for this error, and found it usually has to do something with uncorrect scopes. I however do not see what i am doing wrong here. Is it 'illegal' to have a class instance with the same name as the class?
If i change the initLocal() method to this:
def initLocal(self):
path = input('path:')
locale = local()
locale.path = path
return locale
It works, but i cannot find out why, since controller = controller() does not cause any problems.
Can somebody tell me what i am doing wrong? I have the feeling it might be something really obvious, but i cannot figure out what it is.

class Location:
pass
class Local(location):
path = None
class Controller:
def initLocal(self):
path = raw_input('path:')
local = Local()
local.path = path
return local
controller = Controller()
local = controller.initLocal()

Related

variable inside function not defined despite having it defined globally

I define my dictionary 'frame_dict' outside my for loop. However, when it gets to my forFrame function, despite setting it has a global variable, I get an error saying that frame_dict is not defined. Any help?
import os
from imageai.Detection import VideoObjectDetection
import pickle
PATH_TO_STORE_VIDEOS = "/Users/jaime.pereira/Library/CloudStorage/OneDrive-OneWorkplace/Benchmark_Project/Videos"
tv_commercial_videos = os.listdir('Videos/')
def yolo_neural_network(path_to_videos, tv_commercials):
execution_path = os.getcwd()
frame_dict = {}
for tv_c in tv_commercials:
frame_dict.setdefault(tv_c,[])
# Use pre trained neural network to label things in videos
vid_obj_detect = VideoObjectDetection()
# Set and load Yolo model
vid_obj_detect.setModelTypeAsYOLOv3()
vid_obj_detect.setModelPath(os.path.join(execution_path,"yolov3.pt"))
vid_obj_detect.loadModel()
input_file_path = os.path.join(path_to_videos, tv_c)
if not os.path.exists("output_from_model_yolov3/"):
os.makedirs("output_from_model_yolov3/")
output_file_path = os.path.join(execution_path,"output_from_model_yolov3/", "model_yolov3_output_" + tv_c)
def forFrame(frame_number, output_array, output_count):
global frame_dict
frame_dict[tv_c].append(output_count)
return frame_dict
vid_obj_detect.detectObjectsFromVideo(
input_file_path=input_file_path,
output_file_path=output_file_path,
log_progress=True,
frame_detection_interval= 60,
minimum_percentage_probability=70,
per_frame_function=forFrame,
save_detected_video=True
)
# save dictionary
f = open("yolo_dict.pkl", "wb")
# write dict to pickle file
pickle.dump(frame_dict, f)
# close file
f.close()
return frame_dict
yolo = yolo_neural_network(PATH_TO_STORE_VIDEOS, tv_commercial_videos)
Exception has occurred: ValueError
An error occured. It may be that your input video is invalid. Ensure you specified a proper string value for 'output_file_path' is 'save_detected_video' is not False. Also ensure your per_frame, per_second, per_minute or video_complete_analysis function is properly configured to receive the right parameters.
File "/Users/jaime.pereira/Library/CloudStorage/OneDrive-OneWorkplace/Benchmark_Project/debug.py", line 35, in forFrame
frame_dict[tv_c].append(output_count)
NameError: name 'frame_dict' is not defined
During handling of the above exception, another exception occurred:
File "/Users/jaime.pereira/Library/CloudStorage/OneDrive-OneWorkplace/Benchmark_Project/debug.py", line 38, in yolo_neural_network
vid_obj_detect.detectObjectsFromVideo(
File "/Users/jaime.pereira/Library/CloudStorage/OneDrive-OneWorkplace/Benchmark_Project/debug.py", line 59, in <module>
I tried setting my frame_dict variable as global inside the forframe function expecting it to recognise it.
frame_dict is not a global, it is just in an outer scope, remove global keyword
Since you mutate the object, you don't need to do anything more:
def forFrame(frame_number, output_array, output_count):
frame_dict[tv_c].append(output_count)
return frame_dict
Since you don't assign anything to frame_dict, even if the variable were a global variable, you wouldn't need to add the global keyword if you mutate the object. global is useful only if you need to assign a new value to the variable.
The problem you are facing is that frame_dict is actually not a global variable. It is defined inside of yolo_neural_network. While this is indeed outside forFrame, it is not a global variable.
In this scenario, you should simply remove the global statement, because it is not a global variable you are importing.

os.getenv doesn't work as default value for a function parameter if set within python

With the following code, I'd expect func1 to print the host value (5000) I set twice.
import os
def func1(host = os.getenv("HOST")):
print(host)
print(os.getenv("HOST"))
os.environ["HOST"] = "5000"
func1()
Output:
None
5000
Strange. Let's check the whole list of env vars.
def func2(env = os.environ):
print(env)
os.environ["HOST"] = "5000"
func2()
Output:
environ({..., 'Host': '5000'})
Okay, very strange, so can I grab it using environ?
def func3(host = os.environ["HOST"]):
print(host)
os.environ["HOST"] = "5000"
func3()
Output:
Traceback (most recent call last):
File "mytest.py", line 10, in <module>
def func3(host = os.environ["HOST"]):
File "/Users/me/.pyenv/versions/3.7.3/lib/python3.7/os.py", line 678, in __getitem__
raise KeyError(key) from None
KeyError: 'HOST'
Am I missing something, or this this a bug with python?
I believe the default values are set at runtime not when the function is called. So if you were to set the environment variable above the function declaration it would work.
import os
os.environ["test"] = "test"
def foo(bar=os.environ["test"]):
print(bar)
print(os.environ["test"])
foo()
Output:
test
test
Function default values are evaluated when the function is defined. If you add a line to your script
import os
print(os.getenv("HOST"))
def func1(host = os.getenv("HOST")):
print(host)
print(os.getenv("HOST"))
os.environ["HOST"] = "5000"
func1()
you'll get a preview of what the default value of the host parameter will be. It's the value of HOST as inherited from the parent process, or None if HOST isn't currently in the environment at all.

How to fix the constructor in python

I know that in python the methods have parameter self called implicitly , In my code i cant access the constructor of my class.
class SmartFolder:
def _init_(self,path):
self.path = path
path = "./temp/"
smart_folder = SmartFolder(path)
smart_folder.run()
error:
Traceback (most recent call last):
File "smart_folder.py", line 57, in <module>
smart_folder = SmartFolder(path)
TypeError: SmartFolder() takes no arguments
but i have a constructor which takes arguments.
Please check the indentations and code format. Hope this helps.
class SmartFolder:
def __init__(self,path):
self.path = path
def run(self):
#Your code here
pass
path = "./temp/"
smart_folder = SmartFolder(path)
smart_folder.run()

python default configuration reuse of variables

class DefaultConfig(object):
class S3(object):
DATA_ROOT = 's3://%(bucket_name)s/NAS'
DATA_LOCATION = '{}/%(instrument_id)s/%(run_id)s'.format(DefaultConfig.S3.DATA_ROOT)
The code above gives me the following error.
File "./s3Utils.py", line 5, in <module>
from InfraConfig import InfraConfig as IC
File "/opt/src/datasource/src/main/python/util/InfraConfig.py", line 4, in <module>
class DefaultConfig(object):
File "/opt/src/datasource/src/main/python/util/InfraConfig.py", line 6, in DefaultConfig
class S3(object):
File "/opt/src/datasource/src/main/python/util/InfraConfig.py", line 14, in S3
DATA_LOCATION = '{}/%(instrument_id)s/%(run_id)s'.format(DefaultConfig.S3.DATA_ROOT)
NameError: name 'DefaultConfig' is not defined
Why is it unable to find DefaultConfig.S3.DATA_ROOT
Also, this is my attempt at writing structured configuration with reuse of values of DefaultConfig. Is there a way to do this without writing a yml file?
It is unable to find the DefaultConfing because DefaultConfig is not defined at the moment S3 is created.
Remember that class are objects. Because there are objects, that means they need to be instantiate. Python instantiate a class at the end of its definition, and therefore register it in the globals. Because the class definition is not finished, you can't use the DefaultConfig name.
You should use it without any prefixes:
class DefaultConfig(object):
class S3(object):
DATA_ROOT = 's3://%(bucket_name)s/NAS'
DATA_LOCATION = '{}/%(instrument_id)s/%(run_id)s'.format(DATA_ROOT)
print DefaultConfig.S3.DATA_LOCATION
returns:
> s3://%(bucket_name)s/NAS/%(instrument_id)s/%(run_id)s

Python variable assigned by an outside module is accessible for printing but not for assignment in the target module

I have two files, one is in the webroot, and another is a bootstrap located one folder above the web root (this is CGI programming by the way).
The index file in the web root imports the bootstrap and assigns a variable to it, then calls a a function to initialize the application. Everything up to here works as expected.
Now, in the bootstrap file I can print the variable, but when I try to assign a value to the variable an error is thrown. If you take away the assignment statement no errors are thrown.
I'm really curious about how the scoping works in this situation. I can print the variable, but I can't asign to it. This is on Python 3.
index.py
# Import modules
import sys
import cgitb;
# Enable error reporting
cgitb.enable()
#cgitb.enable(display=0, logdir="/tmp")
# Add the application root to the include path
sys.path.append('path')
# Include the bootstrap
import bootstrap
bootstrap.VAR = 'testVar'
bootstrap.initialize()
bootstrap.py
def initialize():
print('Content-type: text/html\n\n')
print(VAR)
VAR = 'h'
print(VAR)
Thanks.
Edit: The error message
UnboundLocalError: local variable 'VAR' referenced before assignment
args = ("local variable 'VAR' referenced before assignment",)
with_traceback = <built-in method with_traceback of UnboundLocalError object at 0x00C6ACC0>
try this:
def initialize():
global VAR
print('Content-type: text/html\n\n')
print(VAR)
VAR = 'h'
print(VAR)
Without 'global VAR' python want to use local variable VAR and give you "UnboundLocalError: local variable 'VAR' referenced before assignment"
Don't declare it global, pass it instead and return it if you need to have a new value, like this:
def initialize(a):
print('Content-type: text/html\n\n')
print a
return 'h'
----
import bootstrap
b = bootstrap.initialize('testVar')

Categories

Resources