variable inside function not defined despite having it defined globally - python

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.

Related

ProcessPoolExecuter and global variables

I have a question regarding global variables and using different processes.
For my main python script I have a main function which calls Initialize to initialize a global variable in Metrics.py. I've also created a getter function to retrieve this variable.
Main.py:
from Metrics import *
import pprint
def doMultiProcess(Files):
result = {}
with concurrent.futures.ProcessPoolExecutor() as executor:
futures = [executor.submit(ProcessFile, file) for file in Files]
for f in concurrent.futures.as_completed(futures):
# future.result needs to be evaluated to catch any exception
try:
filename, distribution = f.result()
result[filename] = {}
result[filename] = distribution
except Exception as e:
pprint.pprint(e)
return result
Files = ["A.txt", "B.txt", "C.txt"]
def main:
Initialize()
results = doMultiProcess(Files)
if __name__ == '__name__':
main()
Metrics.py
Keywords = ['pragma', 'contract']
def Initialize():
global Keywords
Keywords= ['pragma', 'contract', 'function', 'is']
def GetList():
global Keywords # I believe this is not necessary.
return Keywords
def ProcessFile(filename):
# Read data and extract all the words from the file, then determine the frequency
# distribution of the words, using nltk.freqDist, which is stored in: freqDistTokens
distribution = {keyword:freqDistTokens[keyword] for keyword in Keywords}
return (filename, distribution)
I hope I've simplified the example enough and not left out important information. Now, what I don't understand is why the processes keep working with the initial value of Keywords which contains 'pragma' and 'contract'. I call the initialize before actually running the processes and therefore should set the global variable to something different then the initial value, right? What am I missing that is happening here.
I've worked around this by actually supplying the Keywords list to the process by using the GetList() function but I would like to understand as to why this is happening.

python symbol can be global and local in the same scope

Consider this function:
def content(path):
global file # not useful but valid
with open(path) as file:
return file.read()
When generating a symbol table (using module symtable) and inspecting the symbol file in the scope of the function content, it is global and local at the same time. After calling this function the global name file is bound to the file object. So I wonder why the symbol file in the function scope is also considered as a local symbol?
Here is code to reproduce the behaviour (put it in a file e.g. called global_and_local.py):
import symtable
def content(path):
global file
with open(path) as file:
return file.read()
symtable_root = symtable.symtable(content(__file__), __file__, "exec")
symtable_function = symtable_root.get_children()[0]
symbol_file = symtable_function.lookup('file')
print("symbol 'file' in function scope: is_global() =", symbol_file.is_global())
print("symbol 'file' in function scope: is_local() =", symbol_file.is_local())
print("global scope: file =", file)
The following output is generated:
symbol 'file' in function scope: is_global() = True
symbol 'file' in function scope: is_local() = True
global scope: file = <_io.TextIOWrapper name='global_and_local.py' ...>
For some reason, symtable defines is_local as a check for whether any binding operations for a symbol occur in the scope (or annotations, which are lumped together with annotated assignments at this stage):
def is_local(self):
return bool(self.__flags & DEF_BOUND)
rather than a check for whether the symbol is actually local, which would look like
def is_local(self):
return bool(self.__scope in (LOCAL, CELL))
I'm not sure why. This might be a bug. I don't think modules like this get much use - it took over a year before anyone noticed that adding the // operator broke the old parser module, so I could easily see this going unnoticed.

PythonNameError: name 'discovery' is not defined

Have this below function.But getting error ..any thoughts ?
def zabbix_discovery(pingdom_data):
discovery = []
for k,v in data["recipes"].items():
discovery.append(
{"{#NAME}": str(v['name'])}
)
cmd_args = [
'zabbix_sender',
'-z', config.get('ZABBIX', 'server'),
'-p', config.get('ZABBIX', 'port'),
'-s', config.get('ZABBIX', 'host'),
'-k', config.get('ZABBIX', 'key1'),
'-o', "'{ \"data\": " + discovery + " }'"
]
zabbix_trapper(cmd_args)
=====
Traceback (most recent call last):
File "txncheck_backup.py", line 52, in <module>
'-o', "'{ \"data\": " + discovery + " }'"
NameError: name 'discovery' is not defined
=====
You are using discovery before it is declared on the function call.
Also, as you declare it in the function, it will be destroyed at the end of it and wont be available in the main scope.
You are trying to access it before you call the function zabbix_discovery which assigns value to it. Even if you did correct this logical mistake, you still would not be able to access the discovery variable because it is a local variable. You can either add return discovery to the end of the function and then discovery = zabbix_discovery(pingdom_data), or make it a global variable. Former would look somewhat like this:
discovery = []
def zabbix_discovery(pingdom_data):
global discovery
do what you want to do with it
zabbix_discovery(args)
Also even when you fix these things your code will throw another error because you are trying to access dictionary data in your function, which has no value assigned too. If it is assigned somewhere outside the function, you can easily fix that by adding global data in the beginning of your function.
And why do you have pingdom_data as an argument in your function if you don't use it anywhere?

python function's parameter could not use and one print error

def readswitch(x,y,connn,read):
x='create vlan'
y='global'
conn = sqlite3.connect('server.db')
if conn:
cur = conn.cursor()
run= cur.execute("SELECT command FROM switch WHERE function =? or type = ? ORDER BY key ASC",(x,y))
read = cur.fetchall()
return run;
import database
print (database.readswitch(x,y))
I am trying to access the database and return command in it
I make a module called database could not print it like
Traceback (most recent call last):
File "C:/Users/tommy/PycharmProjects/2015122/database.py", line 400, in <module>
import database
File "C:\Users\tommy\PycharmProjects\2015122\database.py", line 401, in <module>
print (database.readswitch(x,y))
NameError: name 'x' is not defined
and my function parameter could not be used like
def readswitch(x,y,connn,read):
PEP 8: missing whitespace after ',' Parameter 'y' value is not used
how to fix this mistake?
I am not good at python and I need help in this few hours. Thank you!
You define a function with parameter x,y and then you re-assign them within a function. That makes no sense since they are not global variable nor mutable.
I suggest you remove x,y out of function definition or move the assignment to them out to global scope (outside the function).

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