Python exercise error - python-2.7

I am learning Python.
For code:
def main():
fileName = raw_input("file name ")
infile = open(fileName, "r")
sm = 0.0
ct = 0
line = infile.readline()
while line != "":
sm = sm + eval(line)
ct = ct + 1
line = infile.readline()
print "\nAverage is ", sm/ct
main()
it results the following error:
Traceback (most recent call last):
File "/home/sorin/avg6.py", line 13, in <module>
main()
File "/home/sorin/avg6.py", line 8, in main
sm = sm + eval(line)
File "<string>", line 1
^
SyntaxError: unexpected EOF while parsing
I don't understand way. Please help. Thank you.

The eval function expects the string you pass it to be a valid Python expression, but it got an empty string (or, given the while loop's condition, perhaps a string with only whitespace). That doesn't have a value, so it raises an error.
You may want to look in the data file to see if there any blank lines (and remove them, if you can). Or you could modify the code to ignore invalid strings:
while line != "":
try:
sm = sm + eval(line)
ct = ct + 1
except SyntaxError:
pass
line = infile.readline()
You might also want to catch other kinds of errors, if you go that route.
Another option is to explicitly check for specific invalid strings that might come up (like just a bare newline):
while line != "":
if line != "\n": # or maybe us "if line.strip()", to reject whitespace lines
sm = sm + eval(line)
ct = ct + 1
line = infile.readline()
One final suggestion is to use a for loop on the file object rather than a while loop with calls to readline. This won't prevent the kinds of error you're getting, but it generally results in nicer looking code, which might be easier to debug.

What does your input file look like? If your input file has a blank line, it would explain your error.

Related

How can I extract information in the lines between two headers?

I am new to python and am attempting to use this currently nonfunctioning code to extract information between two headers from a text file.
with open('toysystem.txt','r') as f:
start = '<Keywords>'
end = '</Keywords>'
i = 0
lines = f.readlines()
for line in lines:
if line == start:
keywords = lines[i+1]
i += 1
For reference, the text file looks like this:
<Keywords>
GTO
</Keywords>
Any ideas on what might be wrong with the code? Or perhaps a different way to approach this problem?
Thank you!
lines read from file contains newline symbol at the end, so we probably should strip them,
f object is an iterator, so we don't need to use str.readlines method here.
So we can write something like
with open('toysystem.txt', 'r') as f:
start = '<Keywords>'
end = '</Keywords>'
keywords = []
for line in f:
if line.rstrip() == start:
break
for line in f:
if line.rstrip() == end:
break
keywords.append(line)
gives us
>>> keywords
['GTO\n']
If you don't need newline at the end of keywords as well – strip them too:
with open('toysystem.txt', 'r') as f:
start = '<Keywords>'
end = '</Keywords>'
keywords = []
for line in f:
if line.rstrip() == start:
break
for line in f:
if line.rstrip() == end:
break
keywords.append(line.rstrip())
gives
>>> keywords
['GTO']
But in this case it will be better to create stripped lines generator like
with open('toysystem.txt', 'r') as f:
start = '<Keywords>'
end = '</Keywords>'
keywords = []
stripped_lines = (line.rstrip() for line in f)
for line in stripped_lines:
if line == start:
break
for line in stripped_lines:
if line == end:
break
keywords.append(line)
which does the same.
Finally, if you need your lines in the next parts of script, we can use str.readlines and stripped lines generator:
with open('test.txt', 'r') as f:
start = '<Keywords>'
end = '</Keywords>'
keywords = []
lines = f.readlines()
stripped_lines = (line.rstrip() for line in lines)
for line in stripped_lines:
if line.rstrip() == start:
break
for line in stripped_lines:
if line.rstrip() == end:
break
keywords.append(line.rstrip())
gives us
>>> lines
['<Keywords>\n', 'GTO\n', '</Keywords>\n']
>>> keywords
['GTO']
Further reading
file objects,
iterators (including file iterators),
list comprehension,
generator expression
Use Python re module insted and parse it using regex?!
import re
with open('toysystem.txt','r') as f:
contents = f.read()
# will find all the expressions in the file and return a list of values inside the (). You can extend the expression according to your need.
keywords = re.findall(r'\<keywords\>\s*\n*\s*(.*?)\s*\n*\s*\<\/keywords\>')
print(keywords)
from your file it will print
['GTO']
for more about regular expression and python check Tutorialspoint
, For python3 and Python2

How to handle "cannot refer to an open group at position" in Python?

With modified code taken from Python docs, in the tokenizer below I have added regular expression to match docstrings, comments and quotes which are combined into a single master regular expression and successive matches are looped over.
import collections
import re
Token = collections.namedtuple('Token', ['typ', 'value', 'line', 'column'])
def tokenize(code):
keywords = {'IF', 'THEN', 'ENDIF', 'FOR', 'NEXT', 'GOSUB', 'RETURN'}
token_specification = [
('DOC', r'([\'"]{3})[^\x00]*?\2'), # docstrings
('COMM', r'#.*'), # comments
('QUOT', r'(?:"([^"\\\\]*(?:\\.[^"\\\\]*)*)"|' # quotes
r'\'([^\'\\]*(?:\\.[^\'\\]*)*)\')|'
r'r\'([^"(]*)\((.*?)\)\4\'')
]
tok_regex = '|'.join('(?P<%s>%s)' % pair for pair in token_specification)
line_num = 1
line_start = 0
for mo in re.finditer(tok_regex, code):
kind = mo.lastgroup
value = mo.group(kind)
if kind == 'NEWLINE':
line_start = mo.end()
line_num += 1
elif kind == 'SKIP':
pass
elif kind == 'MISMATCH':
raise RuntimeError('%r unexpected on line %d' % (value, line_num))
else:
if kind == 'ID' and value in keywords:
kind = value
column = mo.start() - line_start
yield Token(kind, value, line_num, column)
statements = '''
"""docstr1
blah"""
\'''docstr2\'''
# ok
IF "okkk" and 'ole' quantity THEN
total := total + price * quantity;
tax := price * 0.05;
ENDIF;
'''
for token in tokenize(statements):
print(token)
The above gives the following error:
line 72, in <module>
for token in tokenize(statements),
line 44, in tokenize
for mo in re.finditer(tok_regex, code),
line 220, in finditer
return _compile(pattern, flags).finditer(string),
line 293, in _compile
p = sre_compile.compile(pattern, flags),
line 536, in compile
p = sre_parse.parse(p, flags),
line 829, in parse
p = _parse_sub(source, pattern, 0),
line 437, in _parse_sub
itemsappend(_parse(source, state)),
line 778, in _parse
p = _parse_sub(source, state),
line 437, in _parse_sub
itemsappend(_parse(source, state)),
line 524, in _parse
code = _escape(source, this, state),
line 415, in _escape
len(escape)) sre_constants.error: cannot refer to an open group at position 142
I understand that the problem is the fact that the QUOT regex should be matched before the other two regexes (in case this is too simplistic or plain wrong please do explain).
I am afraid that on some occasions I may end up messing the order of the regexes and not being able to get an error in order to fix it until I provide an appropriate statements.
My question is how could I be able to handle such cases/errors gracefully? Is there a try .. except approach appropriate? Any code example to illustrate this would be great.
(using Python 3.5.1)

Cannot Play After Rename File - TypeError: cannot concatenate 'str' and 'NoneType' objects

I have an error when after rename files and want to access it using the module os.system. namely the script os.system('mpg321' + ren).
I've done os.chdir on the path.
but still it is still not working.
Here I use the power mpg321 for player.
and deliberately did not use the module as pymedia or other.
Traceback (most recent call last):
File "Play_Next.py", line 52, in <module>
os.system('mpg321 ' + ren)
TypeError: cannot concatenate 'str' and 'NoneType' objects
And this my complete script..
import os, time
mypath = 'Mymusic'
filenames = os.listdir(mypath)
len_file = len(filenames)
inp = input('Enter Start Playlist (ex: 2): ')
less = len_file - inp
indexed = filenames[less]
x = os.listdir(mypath)
#pindah_dir = os.chdir(mypath)
#pindah_dir
if x[inp] in x:
print ' [+] Mp3 File indexed: ', indexed
print ' ++++++++++++++++++++++++++++++++ '
os.chdir(mypath)
while True:
try:
time.sleep(0.2)
inp += 1
print x[inp]
inden = x[inp]
rename1 = inden.replace(' ','').replace('-','').replace('(','').replace(')', '').replace("'", '')
ren = os.rename(inden, rename1)
play_next = os.system('mpg321 ' + ren)
play_next
except KeyboardInterrupt:
print "\n\tThankyou.."
break
except IndexError:
print "Repeat from the beginning.."
inp = 0
inp += 1
print x[inp]
Because that os.rename don't return the new file's path like this:
>>> import os
>>> print os.rename('/Users/zookeep/Desktop/test.py', '/Users/zookeep/Desktop/ok.py')
None
You can use os.path.join to get the rename file' name:
>>> os.path.join('/Users/zookeep/Desktop/test.py', 'ok.py')
'/Users/zookeep/Desktop/test.py/ok.py'
So change your code like:
try:
os.rename(inden, rename1)
ren = os.path.join(inden, rename1)
play_next = os.system('mpg321 ' + ren)
except Exception, error:
print error
May helps.

Why searching and displaying search string from files generating error

I am trying to build on example in another question
filter directory in python
and trying to add and return the line found along with filename in which it is found. Here is the code
import os
searchdir = r'C:\Python27\mycode'
searchstring = 'import sys'
def found_in_file(fname, searchstring):
with open(fname) as infp:
for line in infp:
if searchstring in line:
return True, line
return False
with open('found.txt', 'w') as outfp:
count = 0
search_count = 0
for root, dirs, files in os.walk(searchdir):
for name in files:
count += 1
full_name = os.path.join(root, name)
b_found,line = found_in_file(full_name, searchstring)
if b_found:
outfp.write(full_name + '\n')
outfp.writ(line+'\n')
search_count += 1
print 'total number of files found %d' % count
print 'number of files with search string %d' % search_count
I am receiving error
Traceback (most recent call last):
File "C:/Python27/mycode/fsearch", line 20, in <module>
b_found,line = found_in_file(full_name, searchstring)
TypeError: 'bool' object is not iterable
any advise? what am I doing wrong?
If found_in_file hits this line:
return False
a bool is returned. But here
b_found,line = found_in_file(full_name, searchstring)
You expect for two values to be returned. When found_in_file returns, Python thus iterates the returned value to grab the first two values out of it - but it returned a bool, which CAN'T be iterated, and Python gives up and throws an exception: TypeError: 'bool' object is not iterable which is exactly what happened - it tried to iterate a bool to unpack two values from it and could not.
Try return False, None for example.

NZEC in python on spoj for AP2

I wrote the following two codes
FCTRL2.py
import sys;
def fact(x):
res = 1
for i in range (1,x+1):
res=res*i
return res;
t = int(raw_input());
for i in range (0,t):
print fact(int(raw_input()));
and
AP2.py
import sys;
t = int(raw_input());
for i in range (0,t):
x,y,z = map(int,sys.stdin.readline().split())
n = (2*z)/(x+y)
d = (y-x)/(n-5)
a = x-(2*d)
print n
for j in range(0,n):
sys.stdout.write(a+j*d)
sys.stdout.write(' ')
print' '
FCTRL2.py is accepted on spoj whereas AP2.py gives NZEC error. Both work fine on my machine and i do not find much difference with regard to returning values from both. Please explain what is the difference in both and how do i avoid NZEC error for AP2.py
There may be extra white spaces in the input. A good problem setter would ensure that the input satisfies the specified format. But since spoj allows almost anyone to add problems, issues like this sometimes arise. One way to mitigate white space issues is to read the input at once, and then tokenize it.
import sys; # Why use ';'? It's so non-pythonic.
inp = sys.stdin.read().split() # Take whitespaces as delimiter
t = int(inp[0])
readAt = 1
for i in range (0,t):
x,y,z = map(int,inp[readAt:readAt+3]) # Read the next three elements
n = (2*z)/(x+y)
d = (y-x)/(n-5)
a = x-(2*d)
print n
#for j in range(0,n):
# sys.stdout.write(a+j*d)
# sys.stdout.write(' ')
#print ' '
print ' '.join([str(a+ti*d) for ti in xrange(n)]) # More compact and faster
readAt += 3 # Increment the index from which to start the next read
The n in line 10 can be a float, the range function expects an integer. Hence the program exits with an exception.
I tested this on Windows with values:
>ap2.py
23
4 7 9
1.6363636363636365
Traceback (most recent call last):
File "C:\martin\ap2.py", line 10, in <module>
for j in range(0,n):
TypeError: 'float' object cannot be interpreted as an integer