Python string assignment error occurs on second loop, but not first - python

The first run-through of the while loop goes fine:
hour_count = list('00/')
hours = 0
while hours < 24: #loop while hours < 24
hour_count[1] = hours #<- error occurs on this line
hour_count = ''.join(hour_count) #convert to string
...
hours += 1
However, upon the second loop, it gives a TypeError: 'str' object does not support item assignment. The purpose is to set a file path.

When you run this line hour_count = ''.join(hour_count), you're changing the data type of hour_count from a list to a string.
Because strings are immutable, you can't modify one character via the index notation (the line before this line attempts to do that).
I'm not totally sure what your goal is, but perhaps you're looking to append to the list. These docs will help with that.
https://docs.python.org/3.4/tutorial/datastructures.html

You changed the type;
# hour_count at this point is an array
hour_count[1] = hours
# The result of join is a string object
hour_count = ''.join(hour_count)
Next time through hour_count is a string and you can't do "string[1] = ..."

Related

Assigning a variable from a different file with a string

In the file values there are a bunch of lists and I want to assign gun_type to a value depending on what my current_gun_name is plus the string _Iron.
How do I do this? This is my current code but it doesnt work
current_gun_name = string_assigned_above
iron = win32api.GetAsyncKeyState(0x67)
if iron < KeyMin and win32api.GetAsyncKeyState(0x11) < 0:
gun_type = values.(current_gun_name + "_Iron")
So, on the last line there I am trying to pull a list from another file called values. But the list that I am trying to pull depends on the current_gun_name string. For example:
current_string = "test"
list_from_values = values.(current_gun_name + "ing")
print(list_from_values)
In this code it should find a list in the file called values. The list it will find and print will be called "testing" as I am asking it to use the variable plus "ing" Except this doesnt work

How to export int to "txt" file and then at a later date be able to import them back as int 's

Exporting the data:
num = 0
exportData = open("results_file.txt", "a")
while num < len(runs) - 1:
exportData.write(str(runs[num]) + "\n")
num = num + 1
exportData.close()
Importing the data into the new file:
runs = []
num = 1
count = len(open("results_file.txt").readlines( ))
print(count)
importData = open("results_file.txt", "r")
while num < count:
runs.append(importData.read(num))
print(importData.read(num))
num = num + 1
importData.close()
My goal is to export the array of integers to a file (can be something else than a txt file for all I care) and then to import them at a later date into a new file and use them there as integers (performing mathematical operations on them)
The error that I'm getting (on line 28 I'm trying to use the first number in the array for a mathematical calculation):
line 28, in if runs[num] < 7: TypeError: '<' not supported between instances of 'str' and 'int'
runs = []
num = 1
count = len(open("results_file.txt").readlines( ))
print(count)
importData = open("results_file.txt", "r")
while num < count:
runs.append(int(importData.read(num)))
print(importData.read(num))
num = num + 1
importData.close()
Adding int() returns this error:
ValueError: invalid literal for int() with base 10: '4\n1'
You're not being pythonic, and many of the answers here aren't either. So, let me clean up your code a bit.
from ast import literal_eval
with open("results_file.txt", "a") as exportData:
for run in runs:
exportData.write(str(run) + "\n")
runs = []
with open("results_file.txt", "r") as importData:
runs.extend([literal_eval(x) for x in importData])
I'll break this down line by line:
from ast import literal_eval is the safest way to parse things that are strings into python objects. It's better than using a plain old eval because it won't run arbitrary code. We'll use this function to read the data latter.
with open(...) as ... is the best way to open a file. It contains the file-object within a single scope and catches errors. Look this one up here: Pep 343
for ... in ... For loops that you're using are not pythonoic at all. The pythonic way is to use iterators no need to count lines and declare variables to keep track... the python objects keep track of themselves. (If you need a counter I highly recommend that you look up enumerate() Enumerate() in Python
exportData.write(str(run) + "\n") only change here is that with the pythonic for loop there's no need to index the runs list anymore.
runs = [] I think you know what this is, but I have to declare it out of the with statement because if the with statement throws an error, and you were to catch it, runs will be initialized.
I've already discussed with statements.
runs.extend([literal_eval(x) for x in importData]) Has two things going on. extend appends a list to a list... cool. The more interesting part here is the list comprehension. Here's a tutorial on list comprehensions. As soon as you get comfortable with the for loops, the list comprehension is the next pythonic step. For further pythonic enlightenment, this line could also be replaced with: runs.extend(map(literal_eval, importData))
That's it, 9 lines. Happy hacking.
The error you are experiencing is most likely due to the fact you're trying to add a string to an integer. Try doing
runs = []
num = 1
count = len(open("results_file.txt").readlines( ))
print(count)
importData = open("results_file.txt", "r")
while num < count:
runs.append(int(importData.read(num)))
print(importData.read(num))
num = num + 1
importData.close()
The main function/tool you're looking for is int(). For example:
>>> int('15')
15
>>> int('15') + 5
20
But you also can save yourself some real headaches by coding this differently. For example, you do not need to know the number of lines ahead of time. You can just call .readline() until it returns an empty string. Or even iterate over the file and when it ends, it with exit.
Another tip, and this is just good practice, is to use the context manager for opening files. So instead of
file = open('myfile.txt')
for line in file:
print(line)
you would do:
with open('myfile.txt') as file:
for line in file:
print(line)
The big advantage of the latter is that if will always make sure file is closed properly. This is especially helpful when writing to a file.

Assigning multiple return variables, but one at a time?

I am trying to parse some data and format using nltk, but I can't seem to assign multiple returns to multiple variables over a function iteration (see def preprocess function below.) I tried rewriting my code, which usually leads to a big debug, but it seems I am hitting my head against a Python wall that is intentionally there.
def get_7text():
with open('parsed_text/Larrys Pizza & Sports Parlor_text.csv','r') as file:
reader = csv.reader(file)
dict = [row for row in reader]
file.close()
my_dict = [l[0] for l in dict]
text= my_dict[0]
new_dict=ast.literal_eval(text)
for k,v in new_dict.items():
exec(k + '=v')
return Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday
def preprocess():
for day in Days:
day = str(day)
day = sent_tokenize(day)
day = [word_tokenize(s.lower()) for s in day]
day = [pos_tag(s) for s in day]
return day
#code here
Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday = get_7text()
Days=[Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday]
Days=preprocess()
Get7text() returns 7 strings which I can successfully assign. I used to first have it return a dictionary of 7 keys, but formatting was annoying for POS tagging, etc. for NLTK.
The problem is this. Whenever I run preprocess, the program only keeps the 1st item in the list and forgets the other 6. I am trying to force the function to assign each returned output to a list of variables called Days, but to no avail. I also noticed that AFTER Days=preprocess(), Days loses all but the first element (Tuesday through Sunday are empty list of 1 string). However, Days[3] or Days[5] prints the expected data correctly.
I'm expecting there's a better method of representation out there. There are no posts online mentioning it, and it seemed like a sketchy thing to do anyway.
Whenever python sees 'return' it says, "Oh, return, you must be done with your code. I'll stop the function now." As such, it stops after the first iteration. Instead, what you should do is :
def preprocess():
retList = []
for day in Days:
day = str(day)
day = sent_tokenize(day)
day = [word_tokenize(s.lower()) for s in day]
day = [pos_tag(s) for s in day]
retList.append(day)
return (retList)
Naturally, if this doesn't work, then I missed something and we're both at a loss.

Maths quiz for python - str object has no attribute

I've been assigned a task to log student scores for a maths quiz
Below is my task:
The teacher wants to use the results from students taking these quizzes to log their performance. The system should store >the last three scores for each student.
every time I run my code I receive the error:
AttributeError: 'str' object has no attribute 'append'
and when I convert into an int I get this error:
int() argument must be a string, a bytes-like object or a number, not 'NoneType'
import csv
import os
name = input("enter your name: ")
classroom_num = input("enter your classroom number: ")
score = 5
print ("%s, you scored %d/10 questions correctly"%(name,score))
status = open ("state.txt","w") #Every time program is run +1 is added, so that column 1-3 are updated
with open ("state.txt","r") as f:
state = f.read()
if os.stat("state.txt").st_size == 0:
status.write ("0")
state_ints = [ int(x) for x in state.split() ] #converts into int
addone = 1
if state_ints == 3: #If program is run more than 3 times the value in text file reset to 0
state_ints = 0
status.write (state_ints)
with open("Classroom {}.csv".format(classroom_num),"a+") as f:
rows = csv.reader(f)
for row in rows:
if row in rows in row[0] != (name) in row: #Checks if name exists in file (if so name isn't appended to column)
state_ints.append(addone) #Adds one everytime program is run so that score can be replaced for row 1-3
status.write (state_ints)
name_row = (row [0])
name_row.append(name)
score_row = (row (state_ints))
score_row.append(score)
else:
state_ints.append(addone)
status.write (state_ints)
score_row = (row [state_ints])
score_row.append(score)
status.close()
Also what other mistakes might I have made? What can I do to make this more efficient and complete this task?
A string is immutable. You can't change it. You need to make a new string or create a list and make a string of the list when you are done. Also int needs a string of a number to convert. A None type object is a variable with value None. int can't convert None to an integer so you get an error.
The line for row in ("Classroom {}.csv".format(classroom_num)): is iterating over a string, not a file. For each iteration, row is a single character string ('C' then 'l' etc).
row[0] is therefore the same as row and name_row.append(... is trying to call append on a string, hence the "'str' object has no attribute 'append'" error.
I can't see the int() call that's failing but the line state_ints = state_ints.append(addone) is setting state_ints to None. append modifies the list in place and returns None. You just want state_ints.append(addone).
There are several other problems as well that suggest you might want to review a tutorial
Putting a single item in brackets does nothing (an_object) is exactly the same as an_object.
row [state_ints] is trying to use a list as an index (assuming you didn't mean to set it to None
)
status.close should be a method call
if state_ints == 3: state_ints is a list at this point. It's never going to equal 3
etc
See what's going on here?
>>> for row in ("Classroom {}.csv".format("2")):
... print row
...
C
l
a
s
s
r
o
o
m
2
.
c
s
v
>>>
You're not actually opening the file called "Classroom[number].csv" but, instead, you're iterating the characters in the file name.
You can normally use append on the rows of a csv since they are typically transformed into lists (either manually via split(",") or via the csv module) but it fails here since your rows are, in fact, not rows/lists but characters/strings.
You can use with open and manually split by comma or use the csv module for parsing the file. The module approach:
>>> import csv
>>>
>>> with open("Classroom {}.csv".format(classroom_num),"r") as f:
... rows = csv.reader(f)
... for row in rows:
... print(row)
You keep re-using the file handle f when opening files. You also use both with open() and f = open (...). This means that you might be trying to open the same file twice, read from a file you've opened in "append"-mode or other confusing/conflicting actions. Simply stick to With open() - that way, you won't have to manually close the files either.

Python - 'str' object has no attribute 'append'

I've searched this error on here, but haven't seen anything that yet matches my situation (disclaimer, I'm still getting used to Python).
import os
os.chdir("C:\Projects\Rio_Grande\SFR_Checking") # set working directory
stressPeriod = 1
segCounter = 1
inFlow = 0
outFlow = 0
with open(r"C:\Projects\streamflow.dat") as inputFile:
inputList = list(inputFile)
while stressPeriod <= 1:
segCounter = 1
lineCounter = 1
outputFile = open("stats.txt", 'w') # Create the output file
for lineItem in inputList:
if (((stressPeriod - 1) * 11328) + 8) < lineCounter <= (stressPeriod * 11328):
lineItem = lineItem.split()
if int(lineItem[3]) == int(segCounter) and int(lineItem[4]) == int(1):
inFlow = lineItem[5]
outFlow = lineItem[7]
lineItemMem = lineItem
elif int(lineItem[3]) == int(segCounter) and int(lineItem[4]) <> int(1):
outFlow = lineItem[7]
else:
gainLoss = str(float(outFlow) - float(inFlow))
lineItemMem.append(gainLoss)
lineItemMem = ','.join(lineItemMem)
outputFile.write(lineItemMem + "\n") # write # lines to file
segCounter += 1
inFlow = lineItem[5]
outFlow = lineItem[7]
lineCounter += 1
outputFile.close()
So basically this program is supposed to read a .dat file and parse out bits of information from it. I split each line of the file into a list to do some math on it (math operations are between varying lines in the file, which adds complexity to the code). I then append a new number to the end of the list for a given line, and that's where things inexplicably break down. I get the following error:
Traceback (most recent call last):
File "C:/Users/Chuck/Desktop/Python/SFR/SFRParser2.py", line 49, in <module>
lineItemMem.append(gainLoss)
AttributeError: 'str' object has no attribute 'append'
When I give it a print command to test that lineItemMem is actually a list and not a string, it prints a list for me. If I put in code for
lineItemMem.split(",") to break the string, I get an error saying that list object has no attribute split. So basically, when I try to do list operations, the error says its a string, and when I try to do string operations, the error says it's a list. I've tried a fair bit of mucking around, but frankly can't tell what the problem is here. Any insight is appreciated, thanks.
I think the issue has to do with these lines:
lineItemMem.append(gainLoss)
lineItemMem = ','.join(lineItemMem)
Initially lineItemMem is a list, and you can append an item to the end of it. However, the join call you're doing turns the list into a string. That means the next time this part of the code runs, the append call will fail.
I'm not certain exactly what the best solution is. Perhaps you should use a different variable for the string version? Or maybe after you join the list items together into a single string and write that result out, you should reinitialize the lineItemMem variable to a new empty list? You'll have to decide what works best for your actual goals.
There are two places where lineItemMem is set. The first is this:
lineItem = lineItem.split()
# ...
lineItemMem = lineItem
where it is set to the result of a split operation, i.e. a List.
The second place is this:
lineItemMem = ','.join(lineItemMem)
here, it is set to the result of a join operation, i.e. a String.
So, the reason why the error sometimes states that it is a string and sometimes a list is, that that is acutally the case depending on the conditions in the if statement.
The code, as presented, is imho near undebuggable. Instead of tinkering, it would be a better approach to think about the different goals that should be achieved (reading a file, parsing the content, formatting the data, writing it to another file) and tackle them individually.

Categories