'file' object has no attribute '__getitem__' and a missing module - python

I am getting error with this code!!
First the xreadlines module does not exist anymore so i commented the line. Now when i run this code it gives error:
Traceback (most recent call last):
File "/home/integrand/projects/testproject2/testenv/Paragraph.py", line 58, in <module>
show_paragraphs("/home/integrand/projects/testproject2/Files/lease.text")
File "/home/integrand/projects/testproject2/testenv/Paragraph.py", line 50, in show_paragraphs
for p in pp:
File "/home/integrand/projects/testproject2/testenv/Paragraph.py", line 29, in __getitem__
line = self.seq[self.line_num]
TypeError: 'file' object has no attribute '__getitem__'
class Paragraphs:
def __init__(self, fileobj, separator='\n'):
# Ensure that we get a line-reading sequence in the best way possible:
# import xreadlines
try:
# Check if the file-like object has an xreadlines method
self.seq = fileobj.xreadlines()
except AttributeError:
# No, so fall back to the xreadlines module's implementation
self.seq = fileobj.xreadlines()
self.line_num = 0 # current index into self.seq (line number)
self.para_num = 0 # current index into self (paragraph number)
# Ensure that separator string includes a line-end character at the end
if separator[-1:] != '\n': separator += '\n'
self.separator = separator
def __getitem__(self, index):
if index != self.para_num:
raise TypeError, "Only sequential access supported"
self.para_num += 1
# Start where we left off and skip 0+ separator lines
while 1:
# Propagate IndexError, if any, since we're finished if it occurs
line = self.seq[self.line_num]
self.line_num += 1
if line != self.separator: break
# Accumulate 1+ nonempty lines into result
result = [line]
while 1:
# Intercept IndexError, since we have one last paragraph to return
try:
# Let's check if there's at least one more line in self.seq
line = self.seq[self.line_num]
except IndexError:
# self.seq is finished, so we exit the loop
break
# Increment index into self.seq for next time
self.line_num += 1
if line == self.separator: break
result.append(line)
return ''.join(result)
def show_paragraphs(filename,numpars=5):
pp = Paragraphs(open(filename))
for p in pp:
print "Par#%d, line# %d: %s" % (
pp.para_num, pp.line_num, repr(p))
if pp.para_num>numpars: break
if __name__ == '__main__':
#pdfparser("/home/USER/projects/testproject2/Files/Lea.pdf")
show_paragraphs("/home/USER/projects/testproject2/Files/Lea.text")

You can't use subscription on an iterator (which is what file.xreadlines() returns). If you need random access to different lines, just use file.readlines() or list(file) instead.
Note that file.xreadlines() has been deprecated since Python 2.3 (released 13 years ago!); use iteration over the file object instead (which, incidentally, is what list(file) does).

Related

How do I get the output of armstrong program in python?

Am facing the error while executing the below code , could someone help on this?
def getting_input():
while True:
try:
x=int(input("enter the value"))
return x
except Exception as e:
print(f'error: {e}')
continue
class armstrong:
def __init__(self):
self.Lower = getting_input()
self.Upper = getting_input()
def calculation(self):
res=0
a=len(str(self.number))
temp= self.number
while temp > 0:
digit = temp % 10
res += digit ** a
temp //= 10
if self.number == res:
print(self.number)
obj=armstrong()
obj.calculation()
Output:
enter the value1
enter the value50
Traceback (most recent call last):
File "C:\Users\Desktop\TOM\armstrong using list and dic.py", line 25, in <module>
obj.calculation()
File "C:\Users\Desktop\TOM\armstrong using list and dic.py", line 16, in calculation
a=len(str(self.number))
AttributeError: 'armstrong' object has no attribute 'number'
Just like the error says, your 'armstrong' object has no attribute 'number'. I'm not quite sure what you are trying to do, but you are trying to calculate something with self.number, but you never made the attribute in your constructor (__init__). You should do that first.

Turning an object into an iterator in Python 3?

I'm trying to port a library over to Python 3. It has a tokenizer for PDF streams. The reader class calls next() on these tokens. This worked in Python 2, but when I run it in Python 3 I get TypeError: 'PdfTokens' object is not an iterator.
Selections from tokens.py concerning iterators:
class PdfTokens(object):
def __init__(self, fdata, startloc=0, strip_comments=True):
self.fdata = fdata
self.iterator = iterator = self._gettoks(startloc)
self.next = next(iterator)
def __iter__(self):
return self.iterator
def _gettoks(self, startloc, cacheobj=_cacheobj,
delimiters=delimiters, findtok=findtok, findparen=findparen,
PdfString=PdfString, PdfObject=PdfObject):
fdata = self.fdata
current = self.current = [(startloc, startloc)]
namehandler = (cacheobj, self.fixname)
cache = {}
while 1:
for match in findtok(fdata, current[0][1]):
current[0] = tokspan = match.span()
token = match.group(1)
firstch = token[0]
if firstch not in delimiters:
token = cacheobj(cache, token, PdfObject)
elif firstch in '/<(%':
if firstch == '/':
# PDF Name
token = namehandler['#' in token](cache, token, PdfObject)
elif firstch == '<':
# << dict delim, or < hex string >
if token[1:2] != '<':
token = cacheobj(cache, token, PdfString)
elif firstch == '(':
ends = None # For broken strings
if fdata[match.end(1)-1] != ')':
nest = 2
m_start, loc = tokspan
for match in findparen(fdata, loc):
loc = match.end(1)
ending = fdata[loc-1] == ')'
nest += 1 - ending * 2
if not nest:
break
if ending and ends is None:
ends = loc, match.end(), nest
token = fdata[m_start:loc]
current[0] = m_start, match.end()
if nest:
(self.error, self.exception)[not ends]('Unterminated literal string')
loc, ends, nest = ends
token = fdata[m_start:loc] + ')' * nest
current[0] = m_start, ends
token = cacheobj(cache, token, PdfString)
elif firstch == '%':
# Comment
if self.strip_comments:
continue
else:
self.exception('Tokenizer logic incorrect -- should never get here')
yield token
if current[0] is not tokspan:
break
else:
if self.strip_comments:
break
raise StopIteration
The beginning of the offending method in the pdfreader file that raises the error:
def findxref(fdata):
''' Find the cross reference section at the end of a file
'''
startloc = fdata.rfind('startxref')
if startloc < 0:
raise PdfParseError('Did not find "startxref" at end of file')
source = PdfTokens(fdata, startloc, False)
tok = next(source)
I was under the impression that all you needed to define a custom iterator object was a .__iter__method, a .next() method and to raise a StopIteration error. This class has all these things and yet it stills raises the TypeError.
Furthermore, this library and it's methods worked in Python 2.7 and have ceased to work in a Python 3 environment. What about Python 3 has made this different? What can I do to make the PdfTokens object iterable?
You cannot call next on PdfTokens's instance directly, you need to get its iterator first by calling iter() on it. That's exactly what a for-loop does as well*, it calls iter() on the object first and gets an iterator and then within the loop __next__ is invoked on that iterator until it is not exhausted:
instance = PdfTokens(fdata, startloc, False)
source = iter(instance)
tok = next(source)
Well not always, if there's no __iter__ defined on the class then the iterator protocol falls back to __getitem__ if defined.

Unbound method TypeError

I've just been reading an article that talks about implementing a parser in python:
http://effbot.org/zone/simple-top-down-parsing.htm
The general idea behind the code is described in this paper: http://mauke.hopto.org/stuff/papers/p41-pratt.pdf
Being fairly new to writing parsers in python so I'm trying to write something similar as a learning exercise. However when I attempted to try to code up something similar to what was found in the article I am getting an TypeError: unbound method TypeError. This is the first time I've encountered such an error and I've spent all day trying to figure this out but I haven't solved the issue. Here is a minimal code example (in it's entirety) that has this problem:
import re
class Symbol_base(object):
""" A base class for all symbols"""
id = None # node/token type name
value = None #used by literals
first = second = third = None #used by tree nodes
def nud(self):
""" A default implementation for nud """
raise SyntaxError("Syntax error (%r)." % self.id)
def led(self,left):
""" A default implementation for led """
raise SyntaxError("Unknown operator (%r)." % self.id)
def __repr__(self):
if self.id == "(name)" or self.id == "(literal)":
return "(%s %s)" % (self.id[1:-1], self.value)
out = [self.id, self.first, self.second, self.third]
out = map(str, filter(None,out))
return "(" + " ".join(out) + ")"
symbol_table = {}
def symbol(id, bindingpower=0):
""" If a given symbol is found in the symbol_table return it.
If the symblo cannot be found theni create the appropriate class
and add that to the symbol_table."""
try:
s = symbol_table[id]
except KeyError:
class s(Symbol_base):
pass
s.__name__ = "symbol:" + id #for debugging purposes
s.id = id
s.lbp = bindingpower
symbol_table[id] = s
else:
s.lbp = max(bindingpower,s.lbp)
return s
def infix(id, bp):
""" Helper function for defining the symbols for infix operations """
def infix_led(self, left):
self.first = left
self.second = expression(bp)
return self
symbol(id, bp).led = infix_led
#define all the symbols
infix("+", 10)
symbol("(literal)").nud = lambda self: self #literal values must return the symbol itself
symbol("(end)")
token_pat = re.compile("\s*(?:(\d+)|(.))")
def tokenize(program):
for number, operator in token_pat.findall(program):
if number:
symbol = symbol_table["(literal)"]
s = symbol()
s.value = number
yield s
else:
symbol = symbol_table.get(operator)
if not symbol:
raise SyntaxError("Unknown operator")
yield symbol
symbol = symbol_table["(end)"]
yield symbol()
def expression(rbp = 0):
global token
t = token
token = next()
left = t.nud()
while rbp < token.lbp:
t = token
token = next()
left = t.led(left)
return left
def parse(program):
global token, next
next = tokenize(program).next
token = next()
return expression()
def __main__():
print parse("1 + 2")
if __name__ == "__main__":
__main__()
When I try to run this with pypy:
Traceback (most recent call last):
File "app_main.py", line 72, in run_toplevel
File "parser_code_issue.py", line 93, in <module>
__main__()
File "parser_code_issue.py", line 90, in __main__
print parse("1 + 2")
File "parser_code_issue.py", line 87, in parse
return expression()
File "parser_code_issue.py", line 81, in expression
left = t.led(left)
TypeError: unbound method infix_led() must be called with symbol:+ instance as first argument (got symbol:(literal) instance instead)
I'm guessing this happens because I don't create an instance for the infix operations but I'm not really wanting to create an instance at that point. Is there some way I can change those methods without creating instances?
Any help explaining why this is happening and what I can do to fix the code is greatly appreciated!
Also is this behaviour going to change in python 3?
You forgot to create an instance of the symbol in your tokenize() function; when not a number, yield symbol(), not symbol:
else:
symbol = symbol_table.get(operator)
if not symbol:
raise SyntaxError("Unknown operator")
yield symbol()
With that one change your code prints:
(+ (literal 1) (literal 2))
You haven't bound new function to the instance of your object.
import types
obj = symbol(id, bp)
obj.led = types.MethodType(infix_led, obj)
See accepted answer to another SO question

How to Build a dictionary from a text file in Python

I have a text file with entries that look like this :
JohnDoe
Assignment 9
Reading: NO
header: NO
HW: NO
Solutions: 0
show: NO
Journals: NO
free: NO
Finished: NO
Quiz: 0
Done
Assignment 3
E-book: NO
HW: NO
Readings: NO
Show: 0
Journal: NO
Study: NO
Test: NO
Finished: NO
Quiz: 0
Done
This is a small sample. The file has several students in it. Each student has two assignments under their name and they only pass if the line that starts with "Finished" in each assignment reads "Finished: YES". All of the data under each assignment is disorganized, but somewhere under each assignment a line will say "Finished: YES (or NO)" I need a way to read the file and say whether or not any of the students have passed. So far, I have
def get_entries( file ):
with open( "dicrete.txt.rtf", 'rt') as file:
for line in file:
if "Finished" in line:
finished, answer = line.split(':')
yield finished, answer
# dict takes a sequence of `(key, value)` pairs and turns in into a dict
print dict(get_entries( file ))
I can only get this code to return a single entry (the first "Finished" it reads as key and "YES or NO" as value, which is what I want, but I want it to return Every line in the file that that starts with "Finished". So the sample data I provided I want to return a dict with 2 entries {Finished:"NO" , Finished:"NO"}
Dictionaries can only store one mapping per key. So, you can never have a dictionary that has two different entries for the same key.
Consider using a list of two-tuples instead, like [("Finished", "NO"), ("Finished", "NO")].
Sounds like you need a better data model! Let's look at that, shall we?
Let's define an Assignment class that we can call with all the lines of text between Assignment: # and Finished: YES/NO.
class Assignment(object):
def __init__(self, id, *args, **kwargs):
self.id = id
for key,val in kwargs.items():
setattr(self, key.lower(), val)
finished = getattr(self, 'finished', None)
if finished is None:
raise AttributeError("All assignments must have a 'finished' value")
else:
self.finished = True if finished.lower() == "yes" else False
#classmethod
def from_string(cls, s):
"""Builds an Assignment object from a string
a = Assignment.from_string('''Assignment: 1\nAttributes: Go Here\nFinished: yes''')
>>> a.id
1
>>> a.finished
True"""
d = dict()
id = None
for line in s.splitlines():
key,*val = map(str.strip, line.split(":"))
val = ' '.join(val) or None
if key.lower().startswith('assignment'):
id = int(key.split()[-1])
continue
d[key.lower()] = val
if id is not None:
return cls(id, **d)
else:
raise ValueError("No 'Assignment' field in string {}".format(s))
Once you have your model, you'll need to parse your input. Luckily this is actually pretty simple.
def splitlineson(s, sentinel):
"""splits an iterable of strings into a newline separated string beginning with each sentinel.
>>> s = ["Garbage", "lines", "SENT$", "first", "group", "SENT$", "second", "group"]
>>> splitlineson(s, "SENT$")
iter("SENT$\nfirst\ngroup",
"SENT$\nsecond\ngroup")"""
lines = []
for line in s:
if line.lower().strip().startswith(sentinel.lower()):
if any((sentinel.lower() in line.lower() for line in lines)):
yield "\n".join(lines)
lines = [line.strip()]
else:
if line:
lines.append(line.strip())
yield "\n".join(lines)
with open('path/to/textfile.txt') as inf:
assignments = splitlineson(inf, "assignment ")
assignment_list = [Assignment.from_string(a) for a in assignments]

Python Skipping 'for' loop

I'm making a program that searches a file for code snippets. However, in my search procedure, it skips the for loop entirely (inside the search_file procedure). I have looked through my code and have been unable to find a reason. Python seems to just skip all of the code inside the for loop.
import linecache
def load_file(name,mode,dest):
try:
f = open(name,mode)
except IOError:
pass
else:
dest = open(name,mode)
def search_file(f,title,keyword,dest):
found_dots = False
dest.append("")
dest.append("")
dest.append("")
print "hi"
for line in f:
print line
if line == "..":
if found_dots:
print "Done!"
found_dots = False
else:
print "Found dots!"
found_dots = True
elif found_dots:
if line[0:5] == "title=" and line [6:] == title:
dest[0] = line[6:]
elif line[0:5] == "keywd=" and line [6:] == keyword:
dest[1] = line[6:]
else:
dest[2] += line
f = ""
load_file("snippets.txt",'r',f)
search = []
search_file(f,"Open File","file",search)
print search
In Python, arguments are not passed by reference. That is, if you pass in an argument and the function changes that argument (not to be confused with data of that argument), the variable passed in will not be changed.
You're giving load_file an empty string, and that argument is referenced within the function as dest. You do assign dest, but that just assigns the local variable; it does not change f. If you want load_file to return something, you'll have to explicitly return it.
Since f was never changed from an empty string, an empty string is passed to search_file. Looping over a string will loop over the characters, but there are no characters in an empty string, so it does not execute the body of the loop.
Inside each function add global f then f would be treated as a global variable. You don't have to pass f into the functions either.

Categories