Don't understand the cause of this AttributeError - python

What's wrong with that code? When I run it tells me this:
Traceback (most recent call last):
line 24, in <module>
people.append(Dict)
AttributeError: 'str' object has no attribute 'append'
My code:
live = 1
while live == 1:
#reading Database
dataRead = open ("db.txt","r")
if dataRead.read() != " ":
dataRead.close()
people = open ('db.txt','r').read()
do = input ('What Do You Want ? (Search , add) :\n')
#add people
if do == 'add':
#Get The New Data
n_Name = input ('enter the new name:\n')
n_age = input ('enter the new age:\n')
#new Dict
Dict = {'Name:':n_Name,'age':n_age}
people.append(Dict)
#adding people to file
dataWrite = open ("db.txt","w")
dataWrite.write(str(people))
dataWrite.close()
live = 0

The problem is, on line 24, you try to append a dictionary to a string. When you read the db file, it read it as a string. Also the code is really messy and there are a lot better ways to do it. But that's besides the point, the append() method is for lists and the variable "people" is a string, according to your error output.

It says that people is str then it doesn't have an append method. You should just concatenate strings to get them together.
Do:
people += '<append string>'
Have in mind you are trying to append a dictionary to a string. This will throw TypeError cause those type of elements can't be concatenated that way. You should do first: str(dict) to concatenate them.
You're also using a reserved word like dict as a variable. Change it to my_dict or other allowed name.

Related

pickle.load() adds a None object at the end

Hi there, I'm learning Python and trying to create a command-line Address Book as a dictionary, which is saved to a file using pickle (that's the briefing).
I've coded the add_contact and browse_contact functions, and they both work well. I have added a few contacts (whose names are simply "Test One", "Test Two" ... "Test Ten") plus their emails and phone numbers to the Address Book.
However, when I code the search_contact and modify_contact functions, I'll need to load the file back into a dictionary using pickle.load().
The problem is, as each contact was added one by one to the Address Book, if I simply use the following code, it will only return the first object in the Address Book:
with open("addressbook.data", "rb") as f:
loaded_contacts = pickle.load(f)
print(loaded_contacts)
Output:
{'Test One': ('test.one#jdsofj.com', '39893849')}
That's because "Pickle serializes a single object at a time, and reads back a single object." Based on the solution suggested here, I've changed to the following code, so I can load back all the objects into a dictionary called loaded_contacts:
with open("addressbook.data", "rb") as f:
while True:
try:
loaded_contacts = print(pickle.load(f))
except EOFError:
break
That seems to work, but the loaded dictionary from the file will have an extra None object at the end, as shown below once loaded_contacts is printed out:
{'Test One': ('test.one#jdsofj.com', '39893849')}
{'Test Two': ('test.two#clajdf.com', '93294798374')}
.
.
.
{'Test Ten': ('test.ten#oajfd.com', '79854399')}
None
Consequently, when I try to search for a name like "Test One" and try to retrieve its value, I will get TypeError: 'NoneType' object is not subscriptable because there is a None object at the end.
Here's the code (it needs more work but you'll get the idea):
with open("addressbook.data", "rb") as f:
while True:
try:
loaded_contacts = print(pickle.load(f))
except EOFError:
break
search_name = input("Please enter a name: ")
print(loaded_contacts[search_name])
Here's the error message after I enter a name:
TypeError Traceback (most recent call last)
/var/.../x.py in <module>
11
12 search_name = input("Please enter a name: ")
---> 13 print(loaded_contacts[search_name])
14
TypeError: 'NoneType' object is not subscriptable
Not sure what I did wrong, or why there's an extra None object at the end of the loaded dictionary (or how to remove it). I know I could use a list to store all the values as strings, but the briefing is to create a dictionary to hold all the values and use the dictionary built-in methods to add, delete and modify the contacts--and hence my question here.
Edited to update:
Answer to the question (thanks #JohnGordon and #ewong):
In loaded_contacts = print(pickle.load(f)), print() won’t return anything, so assigning a variable to print() will return Noun.
However, simply removing print() won’t fully work—it solves the ‘None’ problem, but loaded_contacts will only be assigned to value of the last iteration of pickle.load(f).
Here's how to iterate all the objects in pickle.load(f) (if they were initially added one-by-one) and then store all of them in a dictionary:
loaded_contacts = {} # create an empty dictionary
with open("addressbook.data", "rb") as f: # open the file
while True: # looping pickle.load(f)
try:
# add each object to the dictionary
loaded_contacts.update(pickle.load(f))
except EOFError:
break # stop looping at the end of the file
loaded_contacts = print(pickle.load(f))
This is your problem. You're assigning loaded_contacts to the return value of print(), which doesn't return anything, so it returns None by default.
Do this instead:
loaded_contacts = pickle.load(f)
print(loaded_contacts)

I'm having trouble with dictionaries in python

I'm writing code with Python. I have defined a lot of dictionaries and a function. I use the dictionary in the function. The dictionary name is the parameter's in function .
I want to get user input which dictionary to use but I don't know how to do this. I tried to get the name of the dictionary with the name in the code line below but it didn't
name=input()
bank("name")
error is:
Traceback (most recent call last):
File "............", line 47, in <module>
banka("hesap")
File "...................", line 18, in banka
print("merhaba",hesap['ad'])
TypeError: string indices must be integers
It's this part of your code:
hesap['ad']
According to the error, hasep is a string, not a dictionary. So you can only put integers into the square brackets.
You could maybe do someting like this
dictionary1 = {}
dictionary2 = {}
user_input = input("Enter 'dictionary1' for dictionary 1 or enter 'dictionary2' for dictionary 2")
if user_input == "dictionary1":
bank(user_input)
elif user_input == "dictionary2":
bank(user_input)
else:
print("unknown command")
Also for your code, when you used the bank function, you put the variable 'name' in speech marks. If you want to input the variable name in the function bank, dont add speech marks. :)
Maybe try doing this:
dict1={...}
dict2={...}
def bank(x):
if x=="dict1":
usedict=dict1
elif x=="dict2":
usedict=dict2
else:
print("No dictionary found with input given")
## write your program using usedict
x=input("enter which dictionary to use")
bank(x)
Remember, if you want to use the dictionary usedict outside the function as well, use global usedict inside the function

Why might python be interpreting my dictionary as a list?

I'm writing a program to sort through csv files. It is supposed to pull lines from the files and based on whether a "donor" is already in the dictionary, either add the "donor" to the dictionary or append the information in the line to the old value. I'm getting the error statement:
error statement: File "C:/Users/riley/Desktop/Python Files/MYLATEST1.py", line 27, in
donors[donor] = [[data]]
builtins.TypeError: list indices must be integers or slices, not tuple
I'm new to python, but it seems as if python is interpreting my dictionary as a list. Is that what's going on? If so, why? Thanks for any help!
def createDonorDirect():
listoffiles = glob.glob('C:/Users/riley/Desktop/mydata//*.csv') #glob allows you to create a list of files/folders that match wildcard expression in this case all the csv files in the directory
# Create donors directory
donors = {}
for filename in listoffiles:
with open(filename) as file:
for line in file:
# line processing stuff
data = line.split(',')
donor = ''.join(data[3,5,7])
# populate data structure
if donor in donors:
donors[donor].append(data)
else:
donors[donor] = [[data]]
The reason for the error is you are assigning donor to tuple value as key, which is wrong here since tuple content multiple values.
sample problem regeneration with code:-
>>> data=['HI','Hello','How','are','you','my','name','is']
>>> donor = ''.join(data[3,5,7])
Traceback (most recent call last):
File "<pyshell#34>", line 1, in <module>
donor = ''.join(data[3,5,7])
**TypeError: list indices must be integers or slices, not tuple**
>>>
second simplified code:-
>>> data[3,5,7]
Traceback (most recent call last):
File "<pyshell#35>", line 1, in <module>
data[3,5,7]
TypeError: list indices must be integers or slices, not tuple
Tuple declaration can be little confusing sometimes.
For example: SOME_CONSTANT = 1, is same as SOME_CONSTANT = (1, ) . Both are a tuple.
On the other hand, SOME_CONSTANT = (1) will be same as SOME_CONSTANT = 1. Both are an integer.
In your case you just need to change:
donor = ''.join(data[3,5,7])
to
donor = ''.join(data[3] + data[5] + data[7])
Example:
data=['A','B','C','D','E','F','G','H']
print ''.join(data[3] + data[5] + data[7])
DFH

Removing duplicates from an attribute of a class variable

I'm extremely new to python and was having some trouble with removing duplicate values from an attribute of a class (I think this is the correct terminology).
Specifically I want to remove every value that is the same year. I should note that I'm printing only the first four value and searching for the first four values. The data within the attribute is actually in Yearmonthday format (example: 19070101 is the year 1907 on the first on january).
Anyways, here is my code:
import csv
import os
class Datatype:
'Data from the weather station'
def __init__ (self, inputline):
[ self.DATE,
self.PRCP] = inputline.split(',')
filename ='LAWe.txt'
LAWd = open(filename, 'r')
LAWefile = LAWd.read()
LAWd.close()
'Recognize the line endings for MS-DOS, UNIX, and Mac and apply the .split() method to the string wholeFile'
if '\r\n' in LAWefile:
filedat = LAWefile.split('\r\n') # the split method, applied to a string, produces a list
elif '\r' in LAWefile:
filedat = LAWefile.split('\r')
else:
filedat = LAWefile.split('\n')
collection = dict()
date= dict()
for thisline in filedat:
thispcp = Datatype(thisline) # here is where the Datatype object is created (running the __init__ function)
collection[thispcp.DATE] = thispcp # the dictionary will be keyed by the ID attribute
for thisID in collection.keys():
studyPRP = collection[thisID]
if studyPRP.DATE.isdigit():
list(studyPRP.DATE)
if len(date[studyPRP.DATE][0:4]):
pass #if year is seen once, then skip and go to next value in attribute
else:
print studyPRP.DATE[0:4] #print value in this case the year)
date[studyPRP.DATE]=studyPRP.DATE[0:4]
I get a this error:
Traceback (most recent call last):
File "project.py", line 61, in
if len(date[studyPRP.DATE][0:4]):
KeyError: '19770509'
A key error (which means a value isn't in a list? but it is for my data) can be fixed by using a set function (or so I've read), but I have 30,000 pieces of information I'm dealing with and it seems like you have to manually type in that info so that's not an option for me.
Any help at all would be appreciated
Sorry if this is confusing or nonsensical as I'm extremely new to python.
Replace this
if len(date[studyPRP.DATE][0:4])
by this
if len(date[studyPRP.DATE[0:4]]):
Explanation :
In the first line you are selecting the whole date as the key KeyError: '19770509' in the 4 first entry of date
In the correction you send the the first 4 character of the date(the year) in the dictionary
Don't know what exactly you want here. I'll reply based on I can help you on what.
Your error is because you are accessing your year in data before you are adding it.
Also, what you are adding to your collection is like
{
<object>.DATE: <object>
}
I don't know what you need here. Your lower for loop can be written as under:
for thisID in collection:
if thisID.isdigit():
if thisID[0:4] in date and len(date[thisID[0:4]]):
#if year is seen once, then skip and go to next
# value in attribute
pass
else:
print thisID[0:4] #print value in this case the year)
date[thisID[0:4]]=thisID[0:4]
Note your studyPRP.DATE is same as thisID.

Appending raw input to a list

This is the simplest of exercises. I just don't understand why it wont work.
Here's my code:
hobbies = []
for i in range(3):
hobby = raw_input("Name a hobby")
hobbies = hobbies.append(hobby)
Basically I want to ask my user 3 times to name one of his hobbies, and store them in a list. But for some reason I'm getting this error,
Traceback (most recent call last):
File "C:/Python27/hobbies.py", line 4, in <module>
hobbies = hobbies.append(hobby)
AttributeError: 'NoneType' object has no attribute 'append'
which I don't really understand.
The problem is that append() will change the list in-place. And when you call this function no value is returned.
The first time you get a None value for the variable hobbies. The second time you try to call the append() method for a None value...
You should not use hobbies = hobbies.append(). Instead use hobbies.append() only.

Categories