ValueError when splitting lines in a text file [closed] - python

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I'd like to split each line of a text file into two by " - ", but I keep getting this error:
File "quiz.py", line 21, in Vocab
questions, answers = line.split("-")
ValueError: too many values to unpack (expected 2)
I'm quite new to coding and could use some help. All tips are welcome as well!
import hashlib
testFile = ""
def qSearch():
options = input ("Vocab/Grammar/or Special? (v/g/s)")
if options == "v":
testFile = "Vocabtest"
Vocab()
elif options == "g":
Grammar()
testFile = "Grammartest"
elif options == "s":
Special()
testFile = "Specialtest"
else:
qSearch()
def Vocab():
with open('Vocabtest.txt','r') as f:
for line in f:
questions, answers = line.split("-") ### error
print (questions)
qSearch()
The text in my text file is formatted like so:
Magandang umaga - Good Morning
Magandang hapon - Good Afternoon
Magandang gabi - Good evening
Magandang umaga sa’yo - Good Morning to you
Magandang hapon din sa’yo - Good Afternoon to you to

"Unpacking" is the name for what you're doing when you write
value1, value2 = a_list
When you do an assignment like that, you're implicitly making an assumption about how many values are contained in a_list -- here it's 2. If there's more or less than 2, there's no good way to give value1 and value2 values without doing very surprising and unhelpful things (like leaving one empty, or leaving some elements of the list unassigned).
So too many values to unpack means that there's at least one line in your file where line.split('-') results in more than 2 elements -- that is, there's at least one line with more than one -.

The problem is because on line 21 in your input text (.txt) file you have more than one - but you only expect one.
A safer way to do it would be to only split once:
questions, answers = line.split("-", 1)

Related

There is no output from file.write [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 3 years ago.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Improve this question
I run the following program and expect to get the output in a .txt file.
I have run this in spyder IDE with python 3.6.
temperatures = [10,-20,-289,100]
file = open('temperature.txt','w')
def f_to_c(temperatures):
for celsius in temperatures:
if celsius > -273.15:
fahrenheit = celsius * (9/5) + 32
file.write(str(fahrenheit))
f_to_c(temperatures)
There is no error message in this code, but I didn't get the output in the .txt file. Can you help?
Updated function and explanation:
def f_to_c(file: str, temps: list):
with open(file, 'a', newline='\n') as f:
for temp in temps:
if temp > -273.15:
fahrenheit = temp * (9/5) + 32
f.write(f'{fahrenheit}\n')
temps = [10,-20,-289,100]
f_to_c('temperature.txt', temps)
Use with open, opens the file, only when the function is called.
The specific reason you never get any output in your file, is because file is never closed.
Using with, will automatically close the file. Reading and Writing Files
Opening the file inside the function, means you won't be looking to the outer scope, to find the file object. Scope of Variables in Python
Use a to append to the file, each time the function is called.
f'{fahrenheit}\n' is an f-string.
PEP 498 -- Literal String Interpolation
Using the f-string, there's no need to convert fahrenheit, using str()
(file: str, temps: list) uses PEP 484 - Type Hints
Alternatively:
Have a dedicated function for converting the temperatures.
This is the appropriate way do deal with the task.
Functions should do one thing.
Deal with the file separately
def f_to_c(temps: list) -> list:
return [temp * (9/5) + 32 for temp in temps if temp > -273.15]
temps = [10,-20,-289,100]
with open('temperature.txt', 'a', newline='\n') as f:
for value in f_to_c(temps):
f.write(f'{value}\n')
The function is implemented with List Comprehensions
The return statement
A cleaner approach below
def f_to_c(temperatures):
fahrenheit_results = []
for celsius in temperatures:
if celsius > -273.15:
fahrenheit_results.append(celsius * (9 / 5) + 32)
return fahrenheit_results
results = f_to_c([10, -20, -289, 100])
with open('out.txt','w') as out:
for r in results:
out.write(str(r) + '\n')

Cannot get output from last elif [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 3 years ago.
Improve this question
I am trying to iterate over a bunch of .xml files in a directory.
For this purpose, I wrote a python script:
#!/usr/bin/python3.5
import os
import glob
pathToDirectory = '/home/anton/Documents/Repo_from_GitHub/ResiShared/templates/'
for filename in os.listdir(pathToDirectory):
file = open(pathToDirectory.__add__(filename), "r")
count = 0
for line in file:
if line.__contains__('xmlns="http://xml.juniper.net/xnm/1.1/xnm"') \
| line.__contains__('xmlns="http://tail-f.com/ned/cisco-ios-xr"') \
| line.__contains__('xmlns="http://tail-f.com/ned/arista-dcs"'):
++count
elif line.__contains__('tags="replace"'):
--count
elif (line.__contains__('</config>') \
| line.__contains__('</config-template>')) & count > 0:
print ('There are ' + str(count) + ' tags="replace" missing in the ' + file.name)
It is working without any bug spotted, but also I got no output from the last "elif", but it definitely should be.
Here is an example of .xml file:
xml file example
UPDATE:
I do not need any kind of XML parser here, core Python functionality should be enough.
python does not support ++ and -- operators. Thus when you do ++count and --count the value of count does not change whatsoever and count > 0 is always False.
And note that it will not raise exception, because it's a valid code. ++count is in fact applying unary operator + twice in a row (i.e. +(+count)). Same for -- (-(-count)).
Given the xml sample file you expect that line.__contains__('</config-template>')) & count > 0 is True but it is not.
All that said - I agree with #King'sjester comment and also why you call dunder methods like __contain__() directly? It makes the code less readable and IMHO ugly to say at least. I would take #mannojlds advice to look in more pythonic tools to parse xml files.
>>> line = 'spam'
>>> count = 0
>>> line.__contains__('eggs') & count > 0
False
EDITED to include explanation on unary operators.
As buran pointed out, there isn't a ++ operator in python, as a result the value of count stays at 0. Changing the following should fix your problem:
++count should be count += 1
--count should be count -= 1
The | symbol is the bitwise operator, instead you should use or.

Python: list index out of range, but there are items in list? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I'm trying to add 18 list items to a 3 text file, 6 items for each them. paths[0] and paths[1] text files are correct but third one paths[2] only gets 3 items.
mainStudents = ["1 Name Surname D1", "2 Name Surname D2" ...16x]
def randomize(path):
count = 0
currentpathIs = getprojdir + "\\" + "\shuffled" + path
print(currentpathIs)
with open(currentpathIs, "a+") as file:
while True:
try:
file.write(mainStudents[count] + "\n")
del(mainStudents[count])
print(count)
count += 1
except Exception as e:
print(mainStudents)
break
if count == 6:
break
randomize(paths[0])
randomize(paths[1])
randomize(paths[2])
I'm getting this error:
Traceback (most recent call last):
File "C:\Users\user\Desktop\New folder\python.py", line 53, in randomize(paths[2])
File "C:\Users\user\Desktop\New folder\python.py", line 43, in randomize
file.write(mainStudents[count] + "\n")
IndexError: list index out of range
But there's 3 items left in mainStudents list?
The problem you have is that when you delete the item from your list, you are then decreasing its size. Therefore, your count is going to increment and then try to access an index that no longer exists. Take a very simple example of just having a list of size two:
mainStudents = ["1 Name Surname D1", "2 Name Surname D2"]
Now, when you call your method, what is going to happen, the first iteration will work, because you will access mainStudents[0].
But, on your second iteration, you have deleted that item from the list, so now your list looks like:
['2 Name Surname D2']
Which is now a list of size one, and the index access for it would be 0.
So, the next iteration of your while loop will have count at 1. Therefore, that is exactly where your IndexError is coming from.
The combination of deciding to use a while loop and del items from your list is what is causing issues. Instead, choose what it is exactly you want to iterate over, which from your logic seems like it is mainStudents. So why not just do that instead?
def randomize(path):
currentpathIs = getprojdir + "\\" + "\shuffled" + path
print(currentpathIs)
with open(currentpathIs, "a+") as file:
for student in mainStudents:
file.write(student + "\n")
And you can further simplify that by simply taking your list and converting it to a string separated by \n by using the available string method, join:
'\n'.join(mainStudents)
Furthermore, there are available methods to facilitate path creation. Take a look at the os module. More specifically os.path.join. So, your code can be further simplified to:
from os.path import join
def randomize(path):
currentpathIs = join(getprojdir, shuffled, path)
with open(currentpathIs, "a+") as file:
file.write('\n'.join(mainStudents))

Reading data from txt file only reads last line [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I'm trying to print data from my text file into python
text_file = open ("Class1.txt", "r")
data = text_file.read().splitlines()
for li in data:
namelist = li.split(":")[0]
scorelist = li.split(":")[1]
print (namelist)
print (scorelist)
text_file.close()
My text file has:
Jim:13524
Harry:3
Jarrod:10
Jacob:0
Harold:5
Charlie:3
Jj:0
It only shows the last entry
Shell:
Would you like to view class 1, 2 or 3? 1
Jj
0
The problem is that you are over-writing the value of namelist and scorelist with each pass through the loop. You need to add each item to a list. Adding a sequential list of items to a list is usually done with list.append() or a list comprehension. Read the documentation, or do some tutorials?
To actually create list, you can do this:
namelist, scorelist = [],[]
for li in data:
namelist.append(li.split(":")[0])
scorelist.append(li.split(":")[1])
Alternately, this might be a better overall approach:
with open("Class1.txt", "r") as text_file:
names_scores = [(e[0],e[1]) for e in [li.split(":") for li in text_file]
for name,score in name_scores:
print(name,score)
This assumes you really just want to extract the names and scores and print them, not do anything else. How you handle and store the data depends a lot on what you are doing with it once you extract from the file.

How to rewrite the code more elegantly [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 6 years ago.
Improve this question
The code below reads lines from a file, then it executes the custom function (My_Function) and return values to the variables(e.g. condition_A)
for line in input_file:
if condition_A:
condition_A = My_Function(A_tuple[0], B_tuple[0])
if condition_B:
condition_B = My_Function(A_tuple[1], B_tuple[1])
if condition_C:
condition_C = My_Function(A_tuple[2], B_tuple[2])
if condition_D:
condition_D = My_Function(A_tuple[3], B_tuple[3])
if condition_E:
condition_E = My_Function(A_tuple[4], B_tuple[4])
...
My question is: can the code be modified to more elegant version? After all, many code is similar(I don't want to define another function to simplify it because the code is still similar after the new function is defined). thanks.
Instead of having 5 variables condition_*, use a list, conditions:
conditions=[1]*5 # initialize conditions as you wish
for line in input_file:
for i,condition in enumerate(conditions):
if condition:
conditions[i]=My_Function(A_tuple[i],B_tuple[i])
What about something like
conditions = [condition_A, condition_B, condition_C, condition_D, condition_E]
condition_test = lambda c, i: My_Function(A_tuple[i], B_tuple[i]) if c else c
for line in input_file:
conditions = [condition_test(c, i) for i, c in enumerate(conditions)]
'line' is not referenced in teh loop, is that an error in simplifying it for posting?
How about
condition=1 #or 2 or...
for line in input_file:
My_Function(A_tuple[condition],B_tuple[condition])
Before refactoring your code on a purely syntactic level (which is covered in examples above), it might be useful to evaluate what you're doing with the code on a functional level
Check out your condition_x variables. I think you might be using the same variable for two different things (both type-wise and logically) - usually a bad idea in a weakly typed language. It looks to me as if the user sets a condition to true or false, and then that condition is assigned the output - is the output boolean? is it related to the original value of that variable? Rethinking this might lead to more understandable code.
It is also difficult to evaluate how this can be refactored without seeing what goes in to condition_x - since these might have commonalities.
One more sample(not solution) based on unutbu's:
data = [1,2,3,'',4,5,6, '', 0]
for i in (i for i in xrange(len(data)) if data[i] not in ['',0]):
data[i] += 1
Sorry if duplicate
Here is a generic solution where you can have custom index and you can also access conditions by name if need be and it can be easily extended to add any new complexities
class Condition(object):
def __init__(self, active, index1, index2):
self.active = active
self.index1 = index1
self.index2 = index2
conditions = {
'A': Condition(True,0,0),
'B': Condition(True,1,1),
'C': Condition(True,2,2),
'D': Condition(True,3,3),
'E': Condition(True,4,4),
}
for line in input_file:
for condition in conditions.itervalues():
if condition.active:
condition.active = My_Function(A_tuple[condition.active.index1], B_tuple[condition.active.index2])

Categories