user6868061 user6868061 - 29 days ago 5x
Python Question

How do I not declare a variable in a loop in Python when I have an except argument

I am trying to iterate through all of the rows on the xml list and write those to csv I need each element value, if it exists, to be written, pipe delimited into the row, or else display a null value. I am able to create the header row and write in the first row of data by using variables, (which is obviously incorrect, but I am very new to python!) Any assistance is appreciated! By the way, please feel free to add anything specific which I could be doing more efficiently or pythonic.

import xml.etree.ElementTree as ET
import sys
import requests
from requests_ntlm import HttpNtlmAuth
import csv

delimiter = '|',
quotechar = '"',
doublequote = True,
skipinitialspace = True,
lineterminator = '\n',
quoting = csv.QUOTE_MINIMAL)

password = "#######"
Username = "YYYY\\XXXXX"

r=requests.get(url, auth=HttpNtlmAuth(Username,password))

tree = ET.fromstring(data) # load the string into a native XML structure

namespaces = {'s': 'uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882','dt': 'uuid:C2F41010-65B3-11d1-A29F-00AA00C14882', 'rs': 'urn:schemas-microsoft-com:rowset', 'z': '#RowsetSchema'}

header_results = tree.findall('./s:Schema/s:ElementType/s:AttributeType', namespaces)
row_results = tree.findall('./rs:data/z:row', namespaces)

with open('c:\output.csv','w') as f:
writer = csv.writer(f, dialect='mydialect')

#This causes the column name to be pipe delimited across the top row of the csv
for header in header_results:
Header_Row += header.attrib['name']+"|"
except KeyError:
Header_Row += "NULL|"

#This part needs help - I need each element value, if it exists, to be written, pipe delimited into the row, or else display a null value
#Currently this only returns one row of data because I am declaring the variable in the loop... how do I accomplish this otherwise?
for result in row_results:
urpid = result.attrib['ows_CnELookup_x003a_URPID']
except KeyError:
urpid = "NULL"
Attachments = result.attrib['ows_Attachments']
except KeyError:
Attachments = "NULL"
Title = result.attrib['ows_LinkTitle']
except KeyError:
Title = "NULL"
Area = result.attrib['ows_Area_x0020_Name']
except KeyError:
Area = "NULL"
Group = result.attrib['ows_Group']
except KeyError:
Group = "NULL"
HITS_Hours = result.attrib['ows_HITS_x0020_Hours']
except KeyError:
HITS_Hours = "NULL"
Consult_Hours = result.attrib['ows_Consultant_x0020_Hours']
except KeyError:
Consult_Hours = "NULL"
Complete = result.attrib['ows_C_x0026_E_x0020_Completed']
except KeyError:
Complete = "NULL"
Area_Order = result.attrib['ows_Area_x0020_Order']
except KeyError:
Area_Order = "NULL"
SP_Row = urpid, Attachments, Title, Area, Group, HITS_Hours, Consult_Hours, Complete, Area_Order

cco cco

Actually, if you indent the last two lines one level, I think you'd have what you're looking for. Your comment in the code mentions "declaring the variable in the loop", but Python variables aren't declared - the only rule is that they must be defined before they are used, which is what you are doing.

As far as a more pythonic way of doing things, the try: ... except KeyError: blocks aren't really the way things are usually done - if you need to get either a stored or default value from a dictionary (named d, for example), use value = d.get(name, default) instead.

Additionally, it looks to me like your header will have an extra | at the end - I'd use this instead:

    Header_Row = [ header.attrib.get('name', 'NULL') for header in header_results ]

In place of your loop over the result rows, I'd use the following code:

    for results in row_results:
        SP_ROW = [  result.attrib.get(key, 'NULL')
                    for key in [ 'ows_CnELookup_x003a_URPID', 'ows_Attachments',
                                 'ows_LinkTitle', 'ows_Area_x0020_Name', 'ows_Group',
                                 'ows_HITS_x0020_Hours', 'ows_Consultant_x0020_Hours',
                                 'ows_C_x0026_E_x0020_Completed', 'ows_Area_x0020_Order' ] ]

Your context manager will make sure the output file is closed, so that should be all you need.