I wrote a script for system automation, but I'm getting the error described in the title. My code below is the relevant portion of the script. What is the problem?
import csv
import os
DIR = "C:/Users/Administrator/Desktop/key_list.csv"
def Customer_List(csv):
customer = open(DIR)
for line in customer:
row = []
(row['MEM_ID'],
row['MEM_SQ'],
row['X_AUTH_USER'],
row['X_AUTH_KEY'],
row['X_STORAGE_URL'],
row['ACCESSKEY'],
row['ACCESSKEYID'],
row['ACCESSKEY1'],
row['ACCESSKEYID1'],
row['ACCESSKEY2'],
row['ACCESSKEYID2'])=line.split()
if csv == row['MEM_ID']:
customer.close()
return(row)
else:
print ("Not search for ID")
return([])
id_input = input("Please input the Customer ID(Email): ")
result = Customer_List(id_input)
if result:
print ("iD: " + id['MEM_ID']
For the line
line.split()
What are you splitting on? Looks like a CSV, so try
line.split(',')
Example:
"one,two,three".split() # returns one element ["one,two,three"]
"one,two,three".split(',') # returns three elements ["one", "two", "three"]
As #TigerhawkT3 mentions, it would be better to use the CSV module. Incredibly quick and easy method available here.
The error message is fairly self-explanatory
(a,b,c,d,e) = line.split()
expects line.split() to yield 5 elements, but in your case, it is only yielding 1 element. This could be because the data is not in the format you expect, a rogue malformed line, or maybe an empty line - there's no way to know.
To see what line is causing the issue, you could add some debug statements like this:
if len(line.split()) != 11:
print line
As Martin suggests, you might also be splitting on the wrong delimiter.
Looks like something is wrong with your data, it isn't in the format you are expecting. It could be a new line character or a blank space in the data that is tinkering with your code.
Related
I have a problem with split function — what I'm doing wrong here?
I get the error:
not enough values to unpack (expected 2, got 1) at the marked line.
The value in line is: ;Electronics:iPhone,3999;Galaxy,2999;Xiaomi,1999.
After the first split, newCategory contains "Electorincs", but products contains only "i".
from collections import defaultdict
import sys
items = open("store.txt" , "r")
categories= dict()
for line in items:
if line == '\n':
break
details= line.split(':')
products=details[1]
newCategory=details[0].lstrip
categories[newCategory]=dict()
products=products[0].split(';')
for p in products:
name,price=p.split(',') # THIS LINE.
name=name.lstrip
price=price.lstrip
categories[newCategory][name]=price
OK, so look at your code, after reading the mentioned line, and splitting the code via ":", You have a list with 2 cells:
#0 contains: Electorincs
#1 contains: iPhone,3999;Galaxy,2999;Xiaomi,1999
SO by reading products[0] you're basically reading the first element of the string iPhone,3999;Galaxy,2999;Xiaomi,1999
you should replace below line
products=products[0].split(';')
with
products=products.split(';')
not sure what you tried to do however the for loop
"for line in items" meaning it brings you character after character and it might be part of the problem
Looking to have my code read one text file and store the line number of a user input as num and then use the variable num to read the same line on another file.
currently, the code for the first step of reading the first text file is working and has been tested but the second part doesn't display anything after being executed. I have changed multiple things but am still stuck. Help would be much appreciated.
here is my code:
print("Check Stock")
ca = input("Check all barcodes?")
if ca == "y":
for x in range(0,5):
with open ("stockbarcodes.txt") as f:
linesa = f.readlines()
print(linesa[x])
with open ("stockname.txt") as f:
linesb = f.readlines()
print(linesb[x])
print(" ")
else:
bc = input("Scan barcode: ")
f1 = open ("stockname.txt")
for num, line in enumerate(f1, 1):
if bc in line:
linesba = f1.readlines()
print(linesba[num])
As user Ikriemer points, it seems that you want to retrieve the stock name based on the barcode. For that kind of task you rather create a normalized Data Base, which discribes Entities, Properties and relationships. As you can se here there are a lot of things to take into account.
This code was tested on Mac OS, but considering OP's comment (who seems to be using windows), it is ok if the dtype is not specified.
Considering that the above solution may not be as quick as you like, you also have two options.
First option
As I can not check the content of your example files, the strategy that you show in your code makes me believe that your assuming both files are ordered, in a way that first line of the barcode file corresponds to first item in the stock name file. Given that, you can query the index of an element (barcode) in an array like data structure, and retrieve the element of another array (name) stored in the same position. Code below:
import numpy as np
print("Check Stock")
ca = input("Check all barcodes? (y/n): ")
if ca == "y":
for x in range(0, 5):
with open("stockbarcodes.txt") as f:
linesa = f.readlines()
print(linesa[x], sep="")
with open("stockname.txt") as f:
linesb = f.readlines()
print(linesb[x], sep="")
print(" ")
else:
try:
codes = np.genfromtxt("stockbarcodes.txt").tolist()
names = np.genfromtxt("stockname.txt", dtype=np.str).tolist()
bc = input("Scan barcode: ")
index = codes.index(int(bc))
print(names[index])
except IndexError:
print("Bar code {} not found".format(bc))
Second option
This option could be considered a workaround method to a data base like file. You need to store your data in some way that you can search the values associated with an specific entry. Such kind of tasks could be done with a dictionary. Just replace the else clause with this:
else:
try:
codes = np.genfromtxt("stockbarcodes.txt").tolist()
names = np.genfromtxt("stockname.txt", dtype=np.str).tolist()
table = {k: v for k, v in zip(codes, names)}
bc = input("Scan barcode: ")
print(table[int(bc)])
except KeyError:
print("Bar code {} not found".format(bc))
Again, in the dictionary comprehension we are assuming both files are ordered. I strongly suggest you to validate this assumption, to warranty that the first bar code corresponds to the first stock, second to second, and so on. Only after that, you may like to store the dictionary as a file, so you can load it and query it as you please. Check this answer fot that purpose.
I have this code, which I want to open a specified file, and then every time there is a while loop it will count it, finally outputting the total number of while loops in a specific file. I decided to convert the input file to a dictionary, and then create a for loop that every time the word while followed by a space was seen it would add a +1 count to WHILE_ before finally printing WHILE_ at the end.
However this did not seem to work, and I am at a loss as to why. Any help fixing this would be much appreciated.
This is the code I have at the moment:
WHILE_ = 0
INPUT_ = input("Enter file or directory: ")
OPEN_ = open(INPUT_)
READLINES_ = OPEN_.readlines()
STRING_ = (str(READLINES_))
STRIP_ = STRING_.strip()
input_str1 = STRIP_.lower()
dic = dict()
for w in input_str1.split():
if w in dic.keys():
dic[w] = dic[w]+1
else:
dic[w] = 1
DICT_ = (dic)
for LINE_ in DICT_:
if ("while\\n',") in LINE_:
WHILE_ += 1
elif ('while\\n",') in LINE_:
WHILE_ += 1
elif ('while ') in LINE_:
WHILE_ += 1
print ("while_loops {0:>12}".format((WHILE_)))
This is the input file I was working from:
'''A trivial test of metrics
Author: Angus McGurkinshaw
Date: May 7 2013
'''
def silly_function(blah):
'''A silly docstring for a silly function'''
def nested():
pass
print('Hello world', blah + 36 * 14)
tot = 0 # This isn't a for statement
for i in range(10):
tot = tot + i
if_im_done = false # Nor is this an if
print(tot)
blah = 3
while blah > 0:
silly_function(blah)
blah -= 1
while True:
if blah < 1000:
break
The output should be 2, but my code at the moment prints 0
This is an incredibly bizarre design. You're calling readlines to get a list of strings, then calling str on that list, which will join the whole thing up into one big string with the quoted repr of each line joined by commas and surrounded by square brackets, then splitting the result on spaces. I have no idea why you'd ever do such a thing.
Your bizarre variable names, extra useless lines of code like DICT_ = (dic), etc. only serve to obfuscate things further.
But I can explain why it doesn't work. Try printing out DICT_ after you do all that silliness, and you'll see that the only keys that include while are while and 'while. Since neither of these match any of the patterns you're looking for, your count ends up as 0.
It's also worth noting that you only add 1 to WHILE_ even if there are multiple instances of the pattern, so your whole dict of counts is useless.
This will be a lot easier if you don't obfuscate your strings, try to recover them, and then try to match the incorrectly-recovered versions. Just do it directly.
While I'm at it, I'm also going to fix some other problems so that your code is readable, and simpler, and doesn't leak files, and so on. Here's a complete implementation of the logic you were trying to hack up by hand:
import collections
filename = input("Enter file: ")
counts = collections.Counter()
with open(filename) as f:
for line in f:
counts.update(line.strip().lower().split())
print('while_loops {0:>12}'.format(counts['while']))
When you run this on your sample input, you correctly get 2. And extending it to handle if and for is trivial and obvious.
However, note that there's a serious problem in your logic: Anything that looks like a keyword but is in the middle of a comment or string will still get picked up. Without writing some kind of code to strip out comments and strings, there's no way around that. Which means you're going to overcount if and for by 1. The obvious way of stripping—line.partition('#')[0] and similarly for quotes—won't work. First, it's perfectly valid to have a string before an if keyword, as in "foo" if x else "bar". Second, you can't handle multiline strings this way.
These problems, and others like them, are why you almost certainly want a real parser. If you're just trying to parse Python code, the ast module in the standard library is the obvious way to do this. If you want to be write quick&dirty parsers for a variety of different languages, try pyparsing, which is very nice, and comes with some great examples.
Here's a simple example:
import ast
filename = input("Enter file: ")
with open(filename) as f:
tree = ast.parse(f.read())
while_loops = sum(1 for node in ast.walk(tree) if isinstance(node, ast.While))
print('while_loops {0:>12}'.format(while_loops))
Or, more flexibly:
import ast
import collections
filename = input("Enter file: ")
with open(filename) as f:
tree = ast.parse(f.read())
counts = collections.Counter(type(node).__name__ for node in ast.walk(tree))
print('while_loops {0:>12}'.format(counts['While']))
print('for_loops {0:>14}'.format(counts['For']))
print('if_statements {0:>10}'.format(counts['If']))
I have an assessment to do, and here's my code so far:
number1 = input("Number1? ")
number2 = input("Number2? ")
packages = csv.reader(open('lol.txt', newline='\n'), delimiter=',')
for PackName,PriceAdultString,PriceChildString in packages:
n += 1
PriceAdult = float(PriceAdultString)
PriceChild = float(PriceChildString)
print("%i. %17s - $%4.2d / $%4.2d" % (n, PackName, PriceAdult, PriceChild))
NameChoice = input("Which name would you like? Choose using a number: ")
The lol.txt used by csv.reader consists of the following:
herp,123,456
derp,321,654
hurr,213,546
Now, I need to be able to use NameChoice to retrieve a row from the file, and use the data within as name, number1, and number2, so for NameChoice == 1, name = herp, number1 = 123 and number 2 = 456, and the numbers must be a floating point number.
I'm having trouble figuring this out, and could use some guidance if that's possible.
Thanks all.
Before it's asked, I realised I forgot to mention: I have googled, and trawled through the Python guides, and my textbooks. I'm not entirely convinced I know what I'm looking for, though.
Run into a new problem:
I need to be able to take CSV text with '\n\n' instead of '\n', so the text is more like the following:
herp,123,456
derp,321,654
hurr,213,546
My (very slightly adjusted) version of the code Li-Aung used:
import csv
with open ("lol.txt",'rt', newline = '\n\n') as f:
csv_r = csv.reader (f)
entries = [ (name, float(p1), float(p2)) for name, p1, p2 in csv_r]
for index, entry in enumerate(entries):
print ("%2i. %-10s %5.2f %5.2f" % (index, entry[0], entry[1], entry[2]))
choice = int(input("Choose a number: "))
print (entries[choice])
Which returns the exception:
Traceback (most recent call last):
File "C:/Python32/eh", line 2, in <module>
with open ("lol.txt",'rt', newline = '\n\n') as f:
ValueError: illegal newline value:
Now, the debug is pretty clear - '\n\n' is not acceptable as a newline specifier, but I was wondering if there is a way around this?
Note: Screwed up the previous edit, the debug from the code with " newline = '\n'" would have been:
Traceback (most recent call last):
File "C:/Python32/eh", line 4, in <module>
entries = [ (name, float(p1), float(p2)) for name, p1, p2 in csv_r]
File "C:/Python32/eh", line 4, in <listcomp>
entries = [ (name, float(p1), float(p2)) for name, p1, p2 in csv_r]
ValueError: need more than 0 values to unpack
Which is because it treated the blank space with 0 values between each useful row as a row, as it was told to do, and there was nothing in there.
#mata has the right of it, but I feel the need to elaborate on their answer more than I can in a comment.
Since you need to refer back to your data instead of just printing it, it makes sense to have it stick around somehow. Once you reach that point, the biggest thing you need to worry about is what kind of data structure to use - if your chosen data structure is a close match to how you want to use the data, the code becomes quite simple.
So, your logic will look like:
Parse the data into some kind of data structure
Walk this data structure to print out the menu
Get the user input, and use it to select the right bit of data
Since the user input is a number representing how far down the file the data is, a list is an obvious choice. If you were using one of the existing fields as a lookup, a dict would serve you better.
If you do:
data = list(csv.reader(open('lol.txt', newline='\n'), delimiter=','))
, you can walk it to print the menu the same way you current use the file, except that the data sticks around, and using the number you get in is directly meaningful.
You might prefer to store the numbers as number types than strings; it would make good sense to, but figuring out how to adjust the code above to achieve it is left as an exercise for the reader. :-)
Store the entire file to a list:
import csv
with open ("lol.txt",'rb') as f:
csv_r = csv.reader (f)
entries = [ (name, float(p1), float(p2)) for name, p1, p2 in csv_r]
for index, entry in enumerate(entries):
print ("%2i. %-10s %5.2f %5.2f" % (index, entry[0], entry[1], entry[2]))
choice = int(raw_input("Choose a number: "))
print (entries[choice])
Output:
0. herp 123.00 456.00
1. derp 321.00 654.00
2. hurr 213.00 546.00
Choose a number: 0
('herp', 123.0, 456.0)
>>>
you could for example store the input in a list instead of just printing it out.
after that it's trivial to get the right tuple from the list and assign it to your variables...
with open ("lol.txt",'rt', newline = '\n\n') as f:
change it to '\n'
with open ("lol.txt",'rt', newline = '\n') as f:
I'm not going to lie. I'm trying to do an assignment and I'm being beaten by it.
I need to have python prompt the user to enter a room number, then lookup that room number in a supplied .txt file which has csv [comma-separated values], and then show multiple results if there are any.
I was able to get python to return the first result ok, but then it stops. I got around the csv thing by using a hash command and .split (I would rather read it as a csv although I couldn't get it to work.) I had to edit the external file so instad of the data being seperated by commas it was seperated by semicolons, which is not ideal as I am not supposed to be messing with the supplied file.
Anyhow...
My external file looks like this:
roombookings.txt
6-3-07;L1;MSW001;1
6-3-07;L2;MSP201;1
6-3-07;L3;WEB201;1
6-3-07;L4;WEB101;1
6-3-07;L5;WEB101;1
7-3-07;L1;MSW001;2
7-3-07;L2;MSP201;2
7-3-07;L3;WEB201;2
7-3-07;L4;WEB101;2
7-3-07;L5;WEB101;2
8-3-07;L1;WEB101;1
8-3-07;L2;MSP201;3
Here's what my code looks like:
roomNumber = (input("Enter the room number: "))
def find_details(id2find):
rb_text = open('roombookings.txt', 'r')
each_line = rb_text.readline()
while each_line != '':
s = {}
(s['Date'], s['Room'], s['Course'], s['Stage']) = each_line.split(";")
if id2find == (s['Room']):
rb_text.close()
return(s)
each_line = rb_text.readline()
rb_text.close()
room = find_details(roomNumber)
if room:
print("Date: " + room['Date'])
print("Room: " + room['Room'])
print("Course: " + room['Course'])
print("Stage: " + room['Stage'])
If i run the program, I get prompted for a room number. If I enter, say, "L1"
I get:
Date: 6-3-07
Room: L1
Course: MSW001
Stage: 1
I should get 3 positive matches. I guess my loop is broken? Please help me save my sanity!
Edit. I've tried the solutions here but keeps either crashing the program (I guess I'm not closing the file properly?) or giving me errors. I've seriously been trying to sort this for 2 days and keep in mind I'm at a VERY basic level. I've read multiple textbooks and done many Google searches but it's all still beyond me, I'm afraid. I appreciate the assistance though.
Your code does "return(s)" the first time the "id2find" argument is exactly equal to the room.
If you want multiple matches, you could create an empty list before entering the loop, append every match to the list WITHOUT returning, return the list, and then use a for-loop to print out each match.
First. For iterating over lines in the file use next:
for line in rb_text:
# do something
Second. Your function returns after first match. How can it match more then one record? Maybe you need something like:
def find_details(id2find):
rb_text = open('roombookings.txt', 'r')
for line in rb_text:
s = {}
(s['Date'], s['Room'], s['Course'], s['Stage']) = line.split(";")
if id2find == (s['Room']):
yield s
rb_text.close()
And then:
for room in find_details(roomNumber):
print("Date: " + room['Date'])
print("Room: " + room['Room'])
print("Course: " + room['Course'])
print("Stage: " + room['Stage'])
And yes, you better use some CSV parser.
Your problem is the return(s) in find_details(). As soon as you have found an entry, you are leaving the function. You do not even close the file then. One solution is to use an empty list at the beginning, e.g results = [], and then append all entries which matches your requirements (results.append(s)).