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.
Related
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)
def get_par(filename_or_pard):
# automatically search for the path
Path = GetPathOsmosisPth()
f = open(Path,'r')
TheLines = f.readlines()
Path = TheLines[0][0:-1] + '/osmosis/'
f.close()
# Get the name of the path to the data
ThePath = locate_dir('GeneralParameters',Path)
Thepdata = ThePath.split('GeneralParameters')[0] #(line 216 - This line gives error)
# check if we do not have provided an external data path
DataDir = CheckInputDataDirectory()
#DataDir = 'Data_CS'
if DataDir is None:
pdata = Thepdata
else:
pdata = os.path.join(Path,DataDir)
# search for the file
if isstring(filename_or_pard):
# myprintv("isstring: ", filename_or_pard)
# creating the dictionary
ThePath = locate(filename_or_pard,pdata)
f = ThePath + os.path.sep + filename_or_pard
pard = create_par_structure(f)
# creating the class par_struct
par = par_struct(pard)
# store the filename with the parameters in the par structure
par.TheFilename = filename_or_pard
else:
# myprint2v("not isstring: ", filename_or_pard, type(filename_or_pard))
# the dictionary is provided as input
pard = filename_or_pard
# creating the class par_struct
if isdict(pard):
par = par_struct(pard)
par._FromStringToTrueType()
else:
par = pard
# if parameters.txt, set the path_data
if hasattr(par,'path_data'):
par.path_data = pdata
par.root_path = Path
# myprintv("pdata: ", par.path_data)
if hasattr(par,'path_packages'):
par.path_packages = os.path.join(Path,par.path_packages)
# returning the result
return par
When i run my program i get an error with both split methods used above. The error displayed is
line 216, in get_par
Thepdata = ThePath.split('GeneralParameters', Path)[0]
AttributeError: 'NoneType' object has no attribute 'split'
I believe i am making a small error but i dont know, just starting programing.
Thanking you in advance
Your function locate_dir returns None. This happens if pattern never matches a path. Since you use your own print function myprinte, you are probably suppressing your error message.
This is assuming your locate_dir is currently formatted as below.
Formatted based on your comment:
def locate_dir(pattern, r=os.curdir):
ok = 0
for path, dirs, files in os.walk(os.path.abspath(r)):
if pattern in path:
ok = 1
return path
if ok == 0: # ok will always be 0 here, you would have left the loop otherwise
myprinte("Warning in locate: No directory found!")
# end of function *implicitly* returns None (i.e. returns "Nothing")
Note that you should raise an Exception if your code fails to produce a result that other code requires.
def locate_dir(pattern, r=os.curdir):
for path, dirs, files in os.walk(os.path.abspath(r)):
if pattern in path:
return path
raise FileNotFoundError("No file found for pattern %s" % pattern)
This way, you do not accidentally suppress errors.
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.
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.
I am trying to parse a file that contains the following
# This is 1st line
# This is 2nd line
ATOM This is 3rd line
ATOM This is 4th line
# This is 5th line
# This is 6th line
I wish to use Python 2.7 to parse the file and append lines up to the line starting with ATOM to a list head_list, the lines starting with ATOM to atom_list and lines after the line containing ATOM to a tail_list.
I want to use the startswith() in Python to match lines that start with ATOM. Below is my code, i am passing counter variable which has the index of the last line in the file which starts with ATOM. yet my output does not seem to be right
#!/usr/bin/python
import sys, os
global counter
def AskForFileName () :
file_name = raw_input('Enter the name of the input file \n')
try:
if not file_name :
print "You did not enter a name !"
except :
exc_type, exc_obj, exc_tb = sys.exc_info()
fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
print(exc_type, fname, exc_tb.tb_lineno)
return file_name
def ReadFileContents (file_name) :
#print file_name
file = open(file_name,'r')
file_strings=file.readlines()
return file_strings
def BuildHeadList(all_file_contents) :
head_list=[]
i=0
try :
for line in all_file_contents:
if line.startswith("ATOM") :
break
else :
i=int(i)+1
#print "BuildHeadList :"+str(i)+"\n"
head_list.append(line)
except :
exc_type, exc_obj, exc_tb = sys.exc_info()
fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
print(exc_type, fname, exc_tb.tb_lineno)
return head_list
def BuildAtomList(all_file_contents) :
atom_list=[]
i=0
global counter
try :
for i,line in enumerate(all_file_contents):
if line.startswith("ATOM") :
atom_list.append(line)
counter=i
#i=int(i)+1
#print "BuildAtomList :"+str(i)+"\n"
else :
continue
except :
exc_type, exc_obj, exc_tb = sys.exc_info()
fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
print(exc_type, fname, exc_tb.tb_lineno)
return atom_list
def BuildTailList(all_file_contents) :
tail_list=[]
i=0
global counter
counter=counter+1
print "Counter value is "+str(counter)
try :
for i,line in enumerate(all_file_contents,counter):
print i
tail_list.append(line)
except :
exc_type, exc_obj, exc_tb = sys.exc_info()
fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
print(exc_type, fname, exc_tb.tb_lineno)
return tail_list
def WriteNewFile(head_list,atom_list,tail_list):
file=open('output.txt', 'w')
#for line in head_list :
# print>>file, line,
#for line in atom_list :
# print>>file, line,
for line in tail_list :
print>>file, line,
file.close()
file_name=AskForFileName()
all_file_contents=ReadFileContents(file_name)
head_list=BuildHeadList(all_file_contents)
atom_list=BuildAtomList(all_file_contents)
tail_list=BuildTailList(all_file_contents )
WriteNewFile(head_list,atom_list,tail_list)
This line:
enumerate(all_file_contents, counter)
Doesn't do what you think it does; it iterates over everything in the lists, but numbers them starting from counter instead of 0. A minimal fix would be:
for i, line in enumerate(all_file_contents):
if i >= counter:
tail_list.append(line)
However, much better would be to not iterate over the whole file three times. In particular, note that tail_list = all_file_contents[counter:] gets the result you want. Additionally, get rid of the global and pass counter around explicitly.
You should also read the style guide.