[Python] global name 'element' not defined

firedrow

Limp Gawd
Joined
Oct 11, 2013
Messages
162
Ok, so I decided to start learning Python. I'm a net admin by trade, with some C/C++ classes years ago. I've started reading Learn Python the Hard Way and I'm over halfway through the book, but I decided to take a break and start working on a little project. So far I've overcome some little issues and moved forward, but now I'm stuck and I'm not seeing the way around.

Code:
# Import helper functions and code
from xml.etree.ElementTree import ElementTree
from xml.parsers.expat import ExpatError

# Define functions
def parse_xml(note_file):
	""" parses the specified XML database """
	results = []
	
	print "ID  | Title"
	
	for element in note_file.getiterator('note'):
		date = element.find('date')
		
		results.append({
			'id' : element.get('id'),
			'title' : element.find('title').text,
			'body' : element.find('body').text,
			'date' : {
				'day' : date.find('day').text,
				'month' : date.find('month').text,
				'year' : date.find('year').text,
			},
		})

def open_xml(tree):
	""" open the XML database, pass it to the parse_xml function """
	try:
		note_file = ElementTree(file = tree)
	except ExpatData:
		print "Unable to parse XML from file"

	parse_xml(note_file)
	
	print element.get('id'), "|", element.find('title').text


noteDB = raw_input('What file would you like to open? ')
open_xml(noteDB)

In Python I get my prompt, then I enter the XML file, then the error "global name 'element' not defined". I'm missing the way to pull variables between functions, and element isn't a simple str or int I can just define "global element" somewhere. I'm probably over my head in coding so far, but the rest of the book work appears to be socket/game coding and I'm looking to build a simple note taking app for now.
 
In your open_xml function,
print element.get('id'), "|", element.find('title').text
...element is not defined. It doesn't know what element is.

The place where element is defined is within your for loop in parse_xml. If you want to use code that interacts with an 'element', it has to go here. The reason for this is something called scope. Scope means to what level within your code something is defined and visible. If I make a variable inside of a function, I can only see it inside of that function...outside, it's not there.

In this case, element is defined inside of the loop because of what element represents. You have a file iterator, which is basically something that gets the next 'thing' in the file every time you call it. For each iteration of the loop, the loop gets the next item in the file and names it 'element'. Then the code inside your loop runs. Once it gets to the bottom of your loop, the program forgets that it named that item 'element' and goes back to the top and repeats the process.

So to start with, I would propose you change your code to look like this as a starting point:
Code:
# Import helper functions and code
from xml.etree.ElementTree import ElementTree
from xml.parsers.expat import ExpatError

# Define functions
def parse_xml(note_file):
	""" parses the specified XML database """
	results = []
	
	print "ID  | Title"
	
	for element in note_file.getiterator('note'):
		print element.get('id'), "|", element.find('title').text

		date = element.find('date')
		
		results.append({
			'id' : element.get('id'),
			'title' : element.find('title').text,
			'body' : element.find('body').text,
			'date' : {
				'day' : date.find('day').text,
				'month' : date.find('month').text,
				'year' : date.find('year').text,
			},
		})

def open_xml(tree):
	""" open the XML database, pass it to the parse_xml function """
	try:
		note_file = ElementTree(file = tree)
	except ExpatData:
		print "Unable to parse XML from file"

	parse_xml(note_file)
	


noteDB = raw_input('What file would you like to open? ')
open_xml(noteDB)

However, there are still some questions left to be answered about your code. For one thing, you're making a list named 'results', and you're adding things to that list, but you don't return the list or do anything with the list, so after you get done filling up the list it just get's deleted. So right now, that's useless.

I'd also like to point out that you will write better code if you follow what's known as the single-responsibility-principal. What that means is each function should only be responsible for one deed. In your open_xml function, you open the XML, but then you also call another function to process the xml, so really open_xml is opening the XML and processing it. It would be better to return note_file in open_xml, and then pass it in to process_xml outside of open_xml.
A decent introduction to the single responsibility principal could be found here:
http://www.codinghorror.com/blog/2007/03/curlys-law-do-one-thing.html
 
The code for results and the append code is left over from troubleshooting how the information was going to be pulled from the XML file. So you're correct, right now I'm not doing anything with it.

Ultimately I do have planned to have everything split out, but I hit the snag and was looking for a way around. If I do the print id and title code from open_xml in parse_xml, then I get the proper output I'm looking for. I'm just kind of staging code right now, eventually this will go into a GUI for a note-taking app I want to use. I do appreciate the help, and I will read the blog link you posted. Thank you.
 
Back
Top