0

I am relatively new on Python.

The program I am writing reads line by line a XML file using a while loop. The data read is split so the information that I get is something like:

datas = ['Name="Date"', 'Tag="0x03442333"', 'Level="Acquisition"', 'Type="String"']

-Inside my program, I want to assign to some variables called exactly as the word before the = sign, the information after the = sign in the previous strings. And then I will introduce them as attributes for a class (this already works) - What I have done until the moment is:

Name = ''
Tag = ''
Level = ''
Type = ''

for i in datas:
    exec(i)

-It works fine that way. However, I do not want to use the exec function. Is there any other way of doing that?

Thank you

JuanLM
  • 1
  • Those who are wondering what's so bad about using `exec` or `eval`, please see [Eval really is dangerous](http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html) by SO veteran Ned Batchelder. – PM 2Ring Apr 01 '16 at 10:22

4 Answers4

1

exec is generally the way to go about this. You could also add it to the globals() dictionary directly, but this would be slightly dangerous sometimes.

for pair in datas:
    name, value = pair.split("=")
    globals()[name] = eval(value)
acdr
  • 4,538
  • 2
  • 19
  • 45
1

You are right that you should avoid exec for security reasons, and you should probably keep the field values in a dict or similar structure. It's better to let a Python library do the whole parsing. For example, using ElementTree:

import xml.etree.ElementTree as ET
tree = ET.parse('myfile.xml')
root = tree.getroot()

and then iterating over root and its children, depending on how exactly your XML data looks like.

Pelle Nilsson
  • 970
  • 8
  • 10
0

At most what you expect to do is discussed here. To convert string to variable name.

But what you should ideally do is to create a dictionary. Like this.

for i in datas:
    (key,value)=i.split("=")
    d[key] = eval(value)

NOTE: Still avoid using eval.

Community
  • 1
  • 1
Leuma S
  • 1
  • 1
0

As Pelle Nilsson says, you should use a proper XML parser for this. However, if the data is simple and the format of your XML file is stable, you can do it by hand.

Do you have a particular reason to put this data into a class? A dictionary may be all you need:

datas = ['Name="Date"', 'Tag="0x03442333"', 'Level="Acquisition"', 'Type="String"']

datadict = {}
for s in datas:
    key, val = s.split('=')
    datadict[key] = val.strip('"')

print(datadict)

output

{'Tag': '0x03442333', 'Type': 'String', 'Name': 'Date', 'Level': 'Acquisition'}

You can pass such a dictionary to a class, if you want:

class MyClass(object):
    def __init__(self, data):
        self.__dict__ = data

    def __repr__(self):
        s = ', '.join('{0}={1!r}'.format(k,v) for k, v in self.__dict__.items())
        return 'Myclass({0})'.format(s)

a = MyClass(datadict)
print(a)
print(a.Name, a.Tag)

output

Myclass(Tag='0x03442333', Type='String', Name='Date', Level='Acquisition')
Date 0x03442333

All of the code in this answer should work correctly on any recent version of Python 2 as well as on Python 3, although if you run it on Python 2 you should put

from __future__ import print_function

at the top of the script.

PM 2Ring
  • 54,345
  • 6
  • 82
  • 182