Python Dictionary from another module , globals() didn't work out - python

file1.py
a = {'fullname':'John Wick', 'Age': 35 , 'job':'Hitman'}
b = {'fullname':'Mark Zuckerberg', 'Age': 30, 'job': 'Developer'}
c = {'fullname':'Will smith', 'Age': 45, 'job': 'Actor'}
d = {'fullname':'Messi' , 'Age': 28, 'job' : 'Player'}
so on... and many more details
Notice : the dict variables are very different.
Task is to obtain "Age" from user input like "Name" or "Job"
for ex: user enters messi... he must get 28 as the output.
File2.py
from File1.py import *
#what should the code be to access the age
user_input=raw_input("enter a Name: ")
# user_input contains the name of the person I want to get the Age
I have tried using globals() but it complicates my situation
It creates a List, which then has to be accessed by integer.
Is there any way to search the values inside the dict and match with IF condition ??

Yes, there are ways to do this, but you're complicating the situation.
First of all, simplify your program even more: pull the remote code into your program file, and solve the access problem there. After that works, then you split it into a second file.
Second, if you want those items to be in a form you can easily search, do that. At the moment, you went out of your way to separate them into distinct variables, when you obviously want to keep them together. Do this in one of two ways:
(1) simple list:
people = [
{'fullname':'John Wick', 'Age': 35 , 'job':'Hitman'},
{'fullname':'Mark Zuckerberg', 'Age': 30, 'job': 'Developer'},
{'fullname':'Will smith', 'Age': 45, 'job': 'Actor'},
{'fullname':'Messi' , 'Age': 28, 'job' : 'Player'}
]
Now, use your normal list search methods to find the matching item.
(2) Dictionary, indexed the way you want to use it:
people = {
'John Wick': {'Age': 35 , 'job':'Hitman'},
'Mark Zuckerberg': {'Age': 30, 'job': 'Developer'},
'Will smith': {'Age': 45, 'job': 'Actor'},
'Messi': {'Age': 28, 'job' : 'Player'}
}
This way, you get the person's record with a direct reference, people[user_input].
Does that get you moving?

try to create a backup of your file1.py as file1.txt and do operations on that very file
sharing a small usefull snippet here
import re
user_input=raw_input("enter a Name: ")
with open("file1.txt") as f:
for line in f:
#print line
matches = re.findall(r'\'(.+?)\'', line)
if user_input in matches:
age = re.findall(r'\d+', line)
print age

Related

Looping through to a placeholder text block and joining each block of text

I'm trying to loop from an array to a block of text with placeholders with Python. However I can't figure out how too append or join the blocks of text under the previous block of text.
How do I loop through an array into a text block with placeholders then output the individual text blocks on top of each other.
My array looks like:
[{'name': James, 'age': 40},{'name': Frank, 'age': 29}]
My placeholder template:
f'''
Profile -
Name: {name}
Age: {age}
'''
I am trying to get to output
Profile -
Name: James
Age: 40
Profile -
Name: Frank
Age: 28
I have tried using both join and concatenation - to no avail i.e:
textBlock = ""
for i in data:
text = f'''Name: {i{'name']}<br>Age: {i{'age']}<br>'''
textBlock.join(text)
Your error was this part {i{'name']} it should be {i['name']} Here try this:
data = [{'name': 'James', 'age': 40},{'name': 'Frank', 'age': 29}]
result = '\n'.join(f'''Name: {i['name']}<br>Age: {i['age']}<br>''' for i in data)
print(result)

Printing Values in Dictionaries

I cannot get values inside my python dictionairy, created from a json file, to print at all. Here is my JSON:
{
"Questions": [
{
"Q1":"What is capital of egypt?",
"T":"London",
"2":"France",
"3":"Egypt"
},
{
"Q2":"What is capital of USA?",
"T":"London",
"2":"France",
"3":"Egypt"
}
]
}
And here is my python:
import json
with open("questions.json") as f:
data = json.load(f)
print(data["Questions"]["Q1"])
This returns the error: list indices must be integers or slices, not str
What am I doing wrong? I have checked the syntax for printing and it all seems correct.
A good strategy is to start by removing code until it works. For example, instead of
print(data["Questions"]["Q1"])`
You should try
print(data["Questions"])`
The output from this is
[{'Q1': 'What is capital of egypt?', 'T': 'London', '2': 'France', '3': 'Egypt'},
{'Q2': 'What is capital of USA?', 'T': 'London', '2': 'France', '3': 'Egypt'}]
From there, you can try to index like you were doing in the question:
[{'Q1': 'What is capital of egypt?', 'T': 'London', '2': 'France', '3': 'Egypt'},
{'Q2': 'What is capital of USA?', 'T': 'London', '2': 'France', '3': 'Egypt'}]['Q1']
Except that doesn't make sense, because you're trying to index a list, and indexes in a list are ints, not strings.
So to get the result you're expecting, you should use data["Questions"][0] to index the first question.
A better solution, in my opinion, is to change the structure of the JSON to something that makes a little more sense. This is how I would do it:
{
"Questions": {
"Q1": {
"Q":"What is capital of egypt?",
"T":"London",
"2":"France",
"3":"Egypt"
},
"Q2" : {
"Q":"What is capital of USA?",
"T":"London",
"2":"France",
"3":"Egypt"
}
}
}
Now you can perform a lookup with Q1 or Q2 just like you expect.
The value of Questions is a list. Like the error says, the index must be an integer.
The first question is going to be data["Questions"][0], the second is data["Questions"][1] and so on.
If you want the value of "Q1" for the first question, you need to use data["Questions"][0]["Q1"]
Try this piece of code:
import json
with open("questions.json") as f:
data = json.load(f)
print(data["Questions"][0]["Q1"], data["Questions"][1]["Q1"])

Python store line by line in List from Text File

i have a text file like so and i would like to process it in python
info.txt
firstname1
surname1
email#email.com1
student1
-------------------
firstname2
surname2
email#email.com2
student2
-----------------
i want to write a python code which iterares and stores each line in each indexs example: [firstname,surname,email#email.com,student] and ignore the "-----"
python code
with open('log.txt') as f:
lines = f.read().splitlines()
x = x + 1
for i in lines:
print i
but i believe this is wrong i amm very new to python can some one please point me in the correct direction
i want the output to me somthing like so
output
index 1 :first name: firstname1
Surname: surname1
Email: email#email.com1
Student student1
index 2 :first name: firstname2
Surname: surname2
Email: email#email.com2
student: student2
I know it'd be better form to explain the general guidelines of how to do something like this, but for a simple task like this, the code speaks for itself, really...
I'd implement it like this.
from pprint import pprint # For nicer formatting of the output.
# For the sake of a self-contained example,
# the data is inlined here.
#
# `f` could be replaced with `open('log.txt').
f = """
firstname1
surname1
email#email.com1
student1
-------------------
firstname2
surname2
email#email.com2
student2
-----------------
""".splitlines()
data = []
current = None
for line in f:
line = line.strip() # Remove leading and trailing spaces
if not line: # Ignore empty lines
continue # Skip the rest of this iteration.
if line.startswith('-----'): # New record.
current = None # Clear the `current` variable
continue # Skip the rest of the iteration
if current is None: # No current entry?
# This can happen either after a ----- line, or
# when we're dealing with the very first line of the file.
current = [] # Create an empty list,
data.append(current) # and push it to the list of data.
current.append(line)
pprint(data)
The output is a list of lists:
[['firstname1', 'surname1', 'email#email.com1', 'student1'],
['firstname2', 'surname2', 'email#email.com2', 'student2']]
Here's a solution that might be a bit more elegant. (As long as your file strictly keeps the format from your example, that is four lines of data followed by a dashed line.)
from itertools import izip # skip this line if you are using Python 3
with open('info.txt') as f:
result = [{'first name': first.strip(), 'Surname': sur.strip(),
'Email': mail.strip(), 'student': stud.strip()}
for first, sur, mail, stud, _ in izip(*[f]*5)]
This gives you a list of dictionaries as follows:
[{'first name': 'firstname1', 'Surname': 'surname1', 'Email': 'email#email.com1', 'student': 'student1'}, {'first name': 'firstname2', 'Surname': 'surname2', 'Email': 'email#email.com2', 'student': 'student2'}]
Where your "index 1" corresponds to the first element of the list (i.e. result[0]), "index 2" corresponds to the second element of the list, and so on.
For example, you can get the surname of your index == 2 with:
index = 2
result[index - 1]['Surname']
If you are really bothered that the index is shifted, you could built a dictionary from the result. Demo:
>>> result = dict(enumerate(result, 1))
>>> result
{1: {'first name': 'firstname1', 'Surname': 'surname1', 'Email': 'email#email.com1', 'student': 'student1'}, 2: {'first name': 'firstname2', 'Surname': 'surname2', 'Email': 'email#email.com2', 'student': 'student2'}}
>>>
>>> result[2]['Surname']
'surname2'
>>>
>>> for index, info in result.items():
... print index, info['first name'], info['Surname'], info['Email'], info['student']
...
1 firstname1 surname1 email#email.com1 student1
2 firstname2 surname2 email#email.com2 student2

Write list of dictionary values to file [duplicate]

This question already has answers here:
Write values of Python dictionary back to file
(2 answers)
Closed 7 years ago.
I have a list of dictionaries such as:
values = [{'Name': 'John Doe', 'Age': 26, 'ID': '1279abc'},
{'Name': 'Jane Smith', 'Age': 35, 'ID': 'bca9721'}
]
What I'd like to do is print this list of dictionaries to a tab delimited text file to look something like this:
Name Age ID
John Doe 26 1279abc
Jane Smith 35 bca9721
However, I am unable to wrap my head around simply printing the values, as of right now I'm printing the entire dictionary per row via:
for i in values:
f.write(str(i))
f.write("\n")
Perhaps I need to iterate through each dictionary now? I've seen people use something like:
for i, n in iterable:
pass
But I've never understood this. Anyone able to shed some light into this?
EDIT:
Appears that I could use something like this, unless someone has a more pythonic way (Perhaps someone can explain "for i, n in interable"?):
for dic in values:
for entry in dic:
f.write(dic[entry])
This is simple enough to accomplish with a DictWriter. Its purpose is to write column-separated data, but if we specify our delimiter to be that of tabs instead of commas, we can make this work just fine.
from csv import DictWriter
values = [{'Name': 'John Doe', 'Age': 26, 'ID': '1279abc'},
{'Name': 'Jane Smith', 'Age': 35, 'ID': 'bca9721'}]
keys = values[0].keys()
with open("new-file.tsv", "w") as f:
dict_writer = DictWriter(f, keys, delimiter="\t")
dict_writer.writeheader()
for value in values:
dict_writer.writerow(value)
f.write('Name\tAge\tID')
for value in values:
f.write('\t'.join([value.get('Name'), str(value.get('Age')), value.get('ID')]))
You're probably thinking of the items() method. This will return the key and value for each entry in the dictionary. http://www.tutorialspoint.com/python/dictionary_items.htm
for k,v in values.items():
pass
# assuming your dictionary is in values
import csv
with open('out.txt', 'w') as fout:
writer = csv.DictWriter(fout, fields=values.keys(). delimiter="\t")
writer.writeheader()
writer.writerow(values.values())

Python: Extract info from xml to dictionary

I need to extract information from an xml file, isolate it from the xml tags before and after, store the information in a dictionary, then loop through the dictionary to print a list. I am an absolute beginner so I'd like to keep it as simple as possible and I apologize if how I've described what I'd like to do doesn't make much sense.
here is what i have so far.
for line in open("/people.xml"):
if "name" in line:
print (line)
if "age" in line:
print(line)
Current Output:
<name>John</name>
<age>14</age>
<name>Kevin</name>
<age>10</age>
<name>Billy</name>
<age>12</age>
Desired Output
Name Age
John 14
Kevin 10
Billy 12
edit- So using the code below I can get the output:
{'Billy': '12', 'John': '14', 'Kevin': '10'}
Does anyone know how to get from this to a chart with headers like my desired output?
try xmldict (Convert xml to python dictionaries, and vice-versa.):
>>> xmldict.xml_to_dict('''
... <root>
... <persons>
... <person>
... <name first="foo" last="bar" />
... </person>
... <person>
... <name first="baz" last="bar" />
... </person>
... </persons>
... </root>
... ''')
{'root': {'persons': {'person': [{'name': {'last': 'bar', 'first': 'foo'}}, {'name': {'last': 'bar', 'first': 'baz'}}]}}}
# Converting dictionary to xml
>>> xmldict.dict_to_xml({'root': {'persons': {'person': [{'name': {'last': 'bar', 'first': 'foo'}}, {'name': {'last': 'bar', 'first': 'baz'}}]}}})
'<root><persons><person><name><last>bar</last><first>foo</first></name></person><person><name><last>bar</last><first>baz</first></name></person></persons></root>'
or try xmlmapper (list of python dictionary with parent-child relationship):
>>> myxml='''<?xml version='1.0' encoding='us-ascii'?>
<slideshow title="Sample Slide Show" date="2012-12-31" author="Yours Truly" >
<slide type="all">
<title>Overview</title>
<item>Why
<em>WonderWidgets</em>
are great
</item>
<item/>
<item>Who
<em>buys</em>
WonderWidgets1
</item>
</slide>
</slideshow>'''
>>> x=xml_to_dict(myxml)
>>> for s in x:
print s
>>>
{'text': '', 'tail': None, 'tag': 'slideshow', 'xmlinfo': {'ownid': 1, 'parentid': 0}, 'xmlattb': {'date': '2012-12-31', 'author': 'Yours Truly', 'title': 'Sample Slide Show'}}
{'text': '', 'tail': '', 'tag': 'slide', 'xmlinfo': {'ownid': 2, 'parentid': 1}, 'xmlattb': {'type': 'all'}}
{'text': 'Overview', 'tail': '', 'tag': 'title', 'xmlinfo': {'ownid': 3, 'parentid': 2}, 'xmlattb': {}}
{'text': 'Why', 'tail': '', 'tag': 'item', 'xmlinfo': {'ownid': 4, 'parentid': 2}, 'xmlattb': {}}
{'text': 'WonderWidgets', 'tail': 'are great', 'tag': 'em', 'xmlinfo': {'ownid': 5, 'parentid': 4}, 'xmlattb': {}}
{'text': None, 'tail': '', 'tag': 'item', 'xmlinfo': {'ownid': 6, 'parentid': 2}, 'xmlattb': {}}
{'text': 'Who', 'tail': '', 'tag': 'item', 'xmlinfo': {'ownid': 7, 'parentid': 2}, 'xmlattb': {}}
{'text': 'buys', 'tail': 'WonderWidgets1', 'tag': 'em', 'xmlinfo': {'ownid': 8, 'parentid': 7}, 'xmlattb': {}}
above code will give generator. When you iterate over it; you will get information in dict keys; like tag, text, xmlattb,tail and addition information in xmlinfo. Here root element will have parentid information as 0.
Use an XML parser for this. For example,
import xml.etree.ElementTree as ET
doc = ET.parse('people.xml')
names = [name.text for name in doc.findall('.//name')]
ages = [age.text for age in doc.findall('.//age')]
people = dict(zip(names,ages))
print(people)
# {'Billy': '12', 'John': '14', 'Kevin': '10'}
It seems to me that this is an exercise in learning how to parse this XML manually rather than simply pulling a library out of the bag to do it for you. If I am wrong, I suggest watching the udacity video by Steve Huffman that can be found here: http://www.udacity.com/view#Course/cs253/CourseRev/apr2012/Unit/362001/Nugget/365002. He explains how to use the minidom module to parse lightweight xml files such as these.
Now, the first point I want to make in my answer, is that you don't want to create a python dictionary to print all of these values. A python dictionary is simply a set of keys that correspond to values. There is no ordering to them, and so traversal in the order they appeared in the file is a pain in the butt. You are trying to print out all of the names together with their corresponding ages, so a data structure like a list of tuples would probably be better suited to collating your data.
It seems like the structure of your xml file is such that each name tag is succeeded by an age tag that corresponds to it. There also seems to only be a single name tag per line. This makes matters fairly simple. I'm not going to write the most efficient or universal solution to this problem, but instead I will try to make the code as simple to understand as I can.
So let's first create a list to store the data:
Let's then create a list to store the data:
a_list = []
Now open your file, and initialize a couple of variables to hold each name and age:
from __future__ import with_statement
with open("/people.xml") as f:
name, age = None, None #initialize a name and an age variable to be used during traversals.
for line in f:
name = extract_name(line,name) # This function will be defined later.
age = extract_age(line) # So will this one.
if age: #We know that if age is defined, we can add a person to our list and reset our variables
a_list.append( (name,age) ) # and now we can re-initialize our variables.
name,age = None , None # otherwise simply read the next line until age is defined.
Now for each line in the file, we wanted to determine whether it contains a user. If it did, we wanted to extract the name. Let's create a function used to do this:
def extract_name(a_line,name): #we pass in the line as well as the name value that that we defined before beginning our traversal.
if name: # if the name is predefined, we simply want to keep the name at its current value. (we can clear it upon encountering the corresponding age.)
return name
if not "<name>" in a_line: #if no "<name>" in a_line, return. otherwise, extract new name.
return
name_pos = a_line.find("<name>")+6
end_pos = a_line.find("</name>")
return a_line[name_pos:end_pos]
Now, we must create a function to parse the line for a user's age. We can do this in a similar way to the previous function, but we know that once we have an age, it will be added into the list immediately. As such, we never need to concern ourselves with age's previous value. The function can therefore look like this:
def extract_age(a_line):
if not "<age>" in a_line: #if no "<age>" in a_line:
return
age_pos = a_line.find("<age>")+5 # else extract age from line and return it.
end_pos = a_line.find("</age>")
return a_line[age_pos:end_pos]
Finally, you want to print the list. You might do it as follows:
for item in a_list:
print '\t'.join(item)
Hope this helped. I haven't tested out my code, so it might still be slightly buggy. The concepts are there, though. :)
Here's another way using lxml library:
from lxml import objectify
def xml_to_dict(xml_str):
""" Convert xml to dict, using lxml v3.4.2 xml processing library, see http://lxml.de/ """
def xml_to_dict_recursion(xml_object):
dict_object = xml_object.__dict__
if not dict_object: # if empty dict returned
return xml_object
for key, value in dict_object.items():
dict_object[key] = xml_to_dict_recursion(value)
return dict_object
return xml_to_dict_recursion(objectify.fromstring(xml_str))
xml_string = """<?xml version="1.0" encoding="UTF-8"?><Response><NewOrderResp>
<IndustryType>Test</IndustryType><SomeData><SomeNestedData1>1234</SomeNestedData1>
<SomeNestedData2>3455</SomeNestedData2></SomeData></NewOrderResp></Response>"""
print xml_to_dict(xml_string)
To preserve the parent node, use this instead:
def xml_to_dict(xml_str):
""" Convert xml to dict, using lxml v3.4.2 xml processing library, see http://lxml.de/ """
def xml_to_dict_recursion(xml_object):
dict_object = xml_object.__dict__
if not dict_object: # if empty dict returned
return xml_object
for key, value in dict_object.items():
dict_object[key] = xml_to_dict_recursion(value)
return dict_object
xml_obj = objectify.fromstring(xml_str)
return {xml_obj.tag: xml_to_dict_recursion(xml_obj)}
And if you want to only return a subtree and convert it to dict, you can use Element.find() :
xml_obj.find('.//') # lxml.objectify.ObjectifiedElement instance
See lxml documentation.

Categories

Resources