Python - index out of range - python

Trying to adapt a basic profiler for bash scripts, block of code below.
Can't figure out why profiling code with a "if branch" throws exception (for example when running this code with a duplicate file). From what I've traced, it somewhere creates an extra index value. My apologies if this is trivial as I'm new to Python, but any suggestions on where could be the issue or how to remedy it would be greatly appreciated
def collect_timings(profiled_line, i):
if i == len(results) - 1:
return [0] + profiled_line
timing = float(results[i+1][1].replace(".N", "")) - float(profiled_line[1].replace(".N", ""))
return [timing] + profiled_line
Error:
Traceback (most recent call last):
File "./profile", line 67, in <module>
main(sys.argv)
File "./profile", line 51, in main
profiling_time = map(collect_timings, results, range(len(results)))
File "./profile", line 24, in collect_timings
timing = float(results[i+1][1].replace(".N", "")) - float(profiled_line[1].replace(".N", ""))
IndexError: list index out of range

Found the answer, posting in case it proves useful for someone.
The issues was a with a output redirection:
echo "Found '$file' is a duplicate of '${filecksums[$cksum]}'" >&2
That got passed as a separate entry to results:
["Found 'txt2/0122file.bck' is a duplicate of 'txt2/0113file.txt'\n"]
No idea how to make the code run with redirects, but it's not necessary, so I'll just avoid it.

you say:
if i == len(results) - 1:
below you say :
timing = float(results[i+1][1].replace(".N", ""))
so you check if "i" show the last element of results array (i.e. results has 5 cells from 0 to 4 and you check if i == 4( len(results) == 5 in this case AND NOT 4) ) and then you say results[i+1] which in the example above is equal to results[5] which is out of bounds.
Maybe you meant results[i]?

Related

Python: IndexError immediately after successful evaluation of list at same index

I am processing a tab-delimited data set of almost three million lines. Since I have enough memory, I am loading the entire data file into memory via a list. I then go and clean up inconsistencies with the data row-by-row. After 150,000 lines of successful computation, the program halts with this error:
Traceback (most recent call last):
File "C:/Users/me/dataset_cleanup_utility/dataset_cleanup.py", line 466, in <module>
ROWS_PASSED = passed
File "C:/Users/me/dataset_cleanup_utility/dataset_cleanup.py", line 43, in dataset_cleanup
row = make_consistent(row, row_count)
File "C:/Users/me/dataset_cleanup_utility/dataset_cleanup.py", line 180, in make_consistent
row[11] = remove("(STAFF)", "", str(row[11]))
IndexError: string index out of range
The code sample that causes this is below:
if "(STAFF)" in str(row[11]):
row[11] = remove("(STAFF)", "", str(row[11]))
def remove(unwanted, wanted, _str):
s = str(_str).rsplit(unwanted, 1)
if len(s) == 2:
return str(s[0]) + wanted + str(s[1])
else:
return str(s[0]) + wanted
Here, row is the list containing all of the columns for a given row and the IndexError is being thrown INSIDE the if statement that checks row[11]. So what this error is telling me is that the row[11] was okay when evaluating the if statement, but inside the if statement, when evaluated again, row[11] no longer exists. How could this be if no changes to row[11] occurred after the if statement was evaluated?

Python - Delete from Array while enumerating

Error:
Traceback (most recent call last):
File "<string>", line 10, in <module>
File "/Users/georg/Programmierung/Glyphs/Glyphs/Glyphs/Scripts/GlyphsApp.py", line 59, in __iter__
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/PyObjC/objc/_convenience.py", line 589, in enumeratorGenerator
yield container_unwrap(anEnumerator.nextObject(), StopIteration)
objc.error: NSGenericException - *** Collection <__NSArrayM: 0x7f9906245480> was mutated while being enumerated.
I know this error occurs because I'm trying to delete objects from the array while also enumerating these objects. But I don't know how to solve it. I'm fairly new to object orientated programming and am limiting myself to scripting.
I searched the web and it seems to solve the error, I have to copy the array before deleting objects from it. When I'm tying to copy the array via deepcopy
import copy
pathcopy = copy.deepcopy(thisLayer.paths)
right before for path in thisLayer.paths:
But in this case I get the following error:
Cannot pickle Objective-C objects
Usually the program crashes after the first Glyph. For clarification: I work in Glyphsapp, a Typedesigning software.
Here is the Code:
# loops through every Glyph and deletes every path with nodes on the left half
for myGlyph in Glyphs.font.glyphs:
glname = myGlyph.name
thisLayer = Glyphs.font.glyphs[glname].layers[1]
middle = thisLayer.bounds.size.width/2+thisLayer.LSB
thisGlyph = thisLayer.parent
for path in thisLayer.paths: # this is where the code crashes
for thisNode in path.nodes:
if thisNode.position.x < middle:
#print thisNode.position.x
try:
thisLayer = path.parent()
except Exception as e:
thisLayer = path.parent
try:
thisLayer.removePath_ ( thisNode.parent() )
except AttributeError:
pass
Thank you in advance
Thank you very much Andreas,
with your help I was able to fix my code :-)
Here is the outcome:
for myGlyph in Glyphs.font.glyphs:
glname = myGlyph.name
thisLayer = Glyphs.font.glyphs[glname].layers[1]
middle = thisLayer.bounds.size.width/2+thisLayer.LSB
thisGlyph = thisLayer.parent
for path in thisLayer.paths:
for thisNode in path.nodes:
if thisNode.position.x < middle:
nodeList = []
nodeList.append(thisNode.parent())
nLCopy = nodeList[:]
for ncontainer in nLCopy:
thisLayer.removePath_ ( ncontainer )

SPOJ: runtime error (NZEC)

I tried to do this problem at spoj.com, but I keep getting the error runtime error (NZEC). I code in python. I don't know why. Here is my code,
import sys
def unique(lines, exact=True):
for L in lines:
if L.count('#') != 1 and exact:
return False
if L.count('#') > 1 and not exact:
return False
return True
def resolve(N, lines):
diags = [
[lines[i][i+j] for i in range(max(0, -j), min(N, N-j))]
for j in range(-N+1, N)]
anti_diags = [
[lines[i][N-1 -(i+j)] for i in range(max(0, -j), min(N, N-j))]
for j in range(-N+1, N)]
if unique(lines) and unique(zip(*lines)) and unique(diags, False) and unique(anti_diags, False):
return "YES"
return "NO"
input_file = sys.stdin
output_file = sys.stdout
T = int(raw_input())
for i in range(1, T + 1):
n = int(raw_input())
lines = []
for _ in range(n):
line = raw_input().strip()
lines.append(list(line))
print resolve(n, lines)
It works fine locally with input like:
2
3
..#
#..
.#.
4
.#..
...#
#...
..#.
When I run your code, I get the following:
$ python spoj.py < input
Traceback (most recent call last):
File "spoj.py", line 38, in <module>
print resolve(n, lines)
File "spoj.py", line 15, in resolve
for j in range(-N+1, N)]
IndexError: list index out of range
That's the runtime error you're getting. But the problem is actually in this part:
for _ in range(n):
line = raw_input().strip()
lines.append(list(line))
print resolve(n, lines)
Since the print statement is indented, your program reads a single line, appends to line and calls resolve before reading the following lines. After removing the extra indent, it works fine on my computer.
There's plenty of room to further improve this program, both in style and logic. Let me know if you would like some further advice.
EDIT:
You mentioned in the comments that this indentation problem was a copypasting error. In that case, as sp1r pointed out in his comment, it's most likely that, as a comment in the problem's page suggests, the input used by the online judge is malformed.
In that case, you have to do more rigorous parsing of the input, as it may not be formatted as the example input suggests. That is, instead of:
2
3
..#
#..
.#.
(etc)
you could have something more like:
2 3
..#
#.. .#.
(etc)
That might break your code because it assumes whoever posted the problem was competent enough to make an input that looks like the example. That is not always the case in SPOJ, a lot of the input files is malformed and you can find other cases where malformed input causes otherwise correct programs to fail.
Spoj does not use sys and sys.stdin and sys.stdout. use raw_input() and print.
"I am on windows not on linux. I simply change this line to switch to console modes for tests."
In any language and in any os, these works fine.
#for Python
spoj.py < input.txt > output.txt
#If you are using C/C++, for any EXE file
spoj.exe < input.txt > output.txt
Spoj will nether test this in your computer nor using any UI. They will test your code, in a "console" and it might be a linux / any-OS machine. Use this input / output to Test your code.

Substring in Python, what is wrong here?

I'm trying to simulate a substring in Python but I'm getting an error:
length_message = len(update)
if length_message > 140:
length_url = len(short['url'])
count_message = 140 - length_url
update = update["msg"][0:count_message] # Substring update variable
print update
return 0
The error is the following:
Traceback (most recent call last):
File "C:\Users\anlopes\workspace\redes_sociais\src\twitterC.py", line 54, in <module>
x.updateTwitterStatus({"url": "http://xxx.com/?cat=49s", "msg": "Searching for some ....... tips?fffffffffffffffffffffffffffffdddddddddddddddddddddddddddddssssssssssssssssssssssssssssssssssssssssssssssssssseeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeedddddddddddddddddddddddddddddddddddddddddddddddfffffffffffffffffffffffffffffffffffffffffffff "})
File "C:\Users\anlopes\workspace\redes_sociais\src\twitterC.py", line 35, in updateTwitterStatus
update = update["msg"][0:count_message]
TypeError: string indices must be integers
I can't do this?
update = update["msg"][0:count_message]
The variable "count_message" return "120"
Give me a clue.
Best Regards,
UPDATE
I make this call, update["msg"] comes from here
x = TwitterC()
x.updateTwitterStatus({"url": "http://xxxx.com/?cat=49", "msg": "Searching for some ...... ....?fffffffffffffffffffffffffffffdddddddddddddddddddddddddddddssssssssssssssssssssssssssssssssssssssssssssssssssseeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeedddddddddddddddddddddddddddddddddddddddddddddddfffffffffffffffffffffffffffffffffffffffffffffddddddddddddddddd"})
Are you looping through this code more than once?
If so, perhaps the first time through update is a dict, and update["msg"] returns a string. Fine.
But you set update equal to the result:
update = update["msg"][0:int(count_message)]
which is (presumably) a string.
If you are looping, the next time through the loop you will have an error because now update is a string, not a dict (and therefore update["msg"] no longer makes sense).
You can debug this by putting in a print statement before the error:
print(type(update))
or, if it is not too large,
print(repr(update))

Unable to have a command line parameter in Python

I run
import sys
print "x \tx^3\tx^3+x^3\t(x+1)^3\tcube+cube=cube+1"
for i in range(sys.argv[2]): // mistake here
cube=i*i*i
cube2=cube+cube
cube3=(i+1)*(i+1)*(i+1)
truth=(cube2==cube3)
print i, "\t", cube, "\t", cube + cube, "\t", cube3, "\t", truth
I get
Traceback (most recent call last):
File "cube.py", line 5, in <module>
for i in range(sys.argv[2]):
IndexError: list index out of range
How can you use command line parameter as follows in the code?
Example of the use
python cube.py 100
It should give
x x^3 x^3+x^3 (x+1)^3 cube+cube=cube+1
0 0 0 1 False
1 1 2 8 False
2 8 16 27 False
--- cut ---
97 912673 1825346 941192 False
98 941192 1882384 970299 False
99 970299 1940598 1000000 False
Use:
sys.argv[1]
also note that arguments are always strings, and range expects an integer.
So the correct code would be:
for i in range(int(sys.argv[1])):
You want int(sys.argv[1]) not 2.
Ideally you would check the length of sys.argv first and print a useful error message if the user doesn't provide the proper arguments.
Edit: See http://www.faqs.org/docs/diveintopython/kgp_commandline.html
Here are some tips on how you can often solve this type of problem yourself:
Read what the error message is telling you: "list index out of range".
What list? Two choices (1) the list returned by range (2) sys.argv
In this case, it can't be (1); it's impossible to get that error out of
for i in range(some_integer) ... but you may not know that, so in general, if there are multiple choices within a line for the source of an error, and you can't see which is the cause, split the line into two or more statements:
num_things = sys.argv[2]
for i in range(num_things):
and run the code again.
By now we know that sys.argv is the list. What index? Must be 2. How come that's out of range? Knowledge-based answer: Because Python counts list indexes from 0. Experiment-based answer: Insert this line before the failing line:
print list(enumerate(sys.argv))
So you need to change the [2] to [1]. Then you will get another error, because in range(n) the n must be an integer, not a string ... and you can work through this new problem in a similar fashion -- extra tip: look up range() in the docs.
I'd like to suggest having a look at Python's argparse module, which is a giant improvement in parsing commandline parameters - it can also do the conversion to int for you including type-checking and error-reporting / generation of help messages.
Its sys.argv[1] instead of 2. You also want to makes sure that you convert that to an integer if you're doing math with it.
so instead of
for i in range(sys.argv[2]):
you want
for i in range(int(sys.argv[1])):

Categories