I have an interesting problem. I am -- for shits and giggles -- trying to write a program really shortly. I have it down to 2 lines, but it has a race condition, and I can't figure out why. Here's the gist of it:
imports...
...[setattr(__main__, 'f', [1, 2, ..]), reduce(...random.choice(f)...)][1]...
Every once in a while, the following exception will be generated. But NOT always. That's my problem. I suspect that the order of execution is not guaranteed especially since I'm using the list trick -- I would assume that maybe the interpreter can predict that setattr() returns None and knows that I'm only selecting the 2nd thing in the list, so it defers the actual setattr() to later. But it only happens sometimes. Any ideas? Does CPython automatically thread some things like map, filter, reduce calls?
Traceback (most recent call last):
File "/usr/lib64/python3.4/random.py", line 253, in choice
i = self._randbelow(len(seq))
File "/usr/lib64/python3.4/random.py", line 230, in _randbelow
r = getrandbits(k) # 0 <= r < 2**k
ValueError: number of bits must be greater than zero
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "test4.py", line 2, in <module>
print(" ".join([setattr(n,'f',open(sys.argv[1],"r").read().replace("\n"," ").split(" ")),setattr(n,'m',c.defaultdict(list)),g.reduce(lambda p,e:p+[r.choice(m[p[-1]])],range(int(sys.argv[2])),[r.choice(list(filter(lambda x:[m[x[0]].append(x[1]),x[0].isupper()][1],zip(f[:-1],f[1:]))))[0]])][2]))
File "test4.py", line 2, in <lambda>
print(" ".join([setattr(n,'f',open(sys.argv[1],"r").read().replace("\n"," ").split(" ")),setattr(n,'m',c.defaultdict(list)),g.reduce(lambda p,e:p+[r.choice(m[p[-1]])],range(int(sys.argv[2])),[r.choice(list(filter(lambda x:[m[x[0]].append(x[1]),x[0].isupper()][1],zip(f[:-1],f[1:]))))[0]])][2]))
File "/usr/lib64/python3.4/random.py", line 255, in choice
raise IndexError('Cannot choose from an empty sequence')
IndexError: Cannot choose from an empty sequence
I've tried modifying globals() and vars() insetad of using setattr(), but that does not seem to help (same exception sequence).
Here's the actual code:
import sys,collections as c,random as r,functools as g,__main__ as n
print(" ".join([setattr(n,'f',open(sys.argv[1],"r").read().replace("\n"," ").split(" ")),setattr(n,'m',c.defaultdict(list)),g.reduce(lambda p,e:p+[r.choice(m[p[-1]])],range(int(sys.argv[2])),[r.choice(list(filter(lambda x:[m[x[0]].append(x[1]),x[0].isupper()][1],zip(f[:-1],f[1:]))))[0]])][2]))
If you're curious: This is to read in a text file, generate a Markov model, and spit out a sentence.
random.choice()
Well, of course that is nondeterministic. If you are very careful, you could set the seed of the pseudo-random number generator to something constant, and hope that's fabricates the same sequence every time. There's a good chance it will work.
random.seed(42); ...
Alright, here's what actually happened: In my sentence generation, I sometimes hit the last word in the file (which in some cases, depending on the file, does not have a possible successor state). Hence, I'm trying to choose from an empty list in that case.
Related
I'm trying to add a player to a board in python, but am struggling with the implmentation.
The player object's attributes gets validated when a player is initiated via the operator library. I want to show the exceptions as they occur; ie. put the initiation of each player in a try-except.
Problem is that when I do it as I am bellow I get an error saying:
Traceback (most recent call last): File "./main.py", line 88, in
move
r.forward() AttributeError: 'NoneType' object has no attribute 'forward'
During handling of the above exception, another exception occurred:
Traceback (most recent call last): File "./main.py", line 161, in
main() File "./main.py", line 141, in main
move(choice, player) # Peform the moves on the player File "./main.py", line 91, in move
Try again!\n>>> ".format(err, r.initial[0], r.initial[1], r.initial[2])) AttributeError: 'NoneType' object has no attribute
'initial'
The operations mentioned above are movements handled by the player class (player.py). It's clear that I am somehow returning a NoneType, but I'm not sure why this is occuring.
It happens when I have entered an incorrect player-position during initiation and then add a correct one.
So basically this is what I do:
Initiate the board
Initiate a player outside of bounds (or on another player)
Initiate a correct player position.
Error occurs.
However, there are no errors if I add players correctly (ie. step 3 doesn't occur).
def add_player(board):
try:
choice = input("Please enter the current player's initial position.\nRemember to keep inside board's limits!\n>>> ").split()
if len(choice) == 3 and validate_player(choice[0], choice[1], choice[2]): # Check the length of supplied input and check type-integrity
return Player(int(choice[0]), int(choice[1]), choice[2], board) # Initiate a player with the supplied input. Each player is assigned to a Board (many-to-one relation).
except Exception as err:
print(err)
add_player(board)
There are several possible problems here. Firstly, if the if statement does not evaluate to True, nothing is returned from the function. No exception would be raised so the except block wouldn't be entered, but nothing else is returned either; None is the default return value when nothing else is returned.
Secondly, even if there was an exception, you are not returning the result from the recursive call to add_player in the except block. However you should not be using recursion here, you should loop until the right values are entered.
Unrelated, but you should never catch the base Exception; you should only catch the things that you might expect, which in this case are ValueError (from the int call, if something other than a number is entered) and IndexError (from the indexing into list, if less than three items are entered). Catch those exceptions only.
Traceback (most recent call last):
File "C:\Users\sahib navlani\Desktop\gfh.py", line 107, in <module>
main()
File "C:\Users\sahib navlani\Desktop\gfh.py", line 98, in main
crit2.play()
File "C:\Users\sahib navlani\Desktop\gfh.py", line 34, in play
self.play -= play1
TypeError: unsupported operand type(s) for -=: 'instancemethod' and 'int'
I get this error whenever i put this code . I think this due to line self.play -= play
play1 = int(raw_input("Please enter the time for which you want to play = "))
self.play -= play1
It's because self.play is a member method. I think you have done mixing of names of member methods and member names. Give proper names to variables and be clear about the purpose for which you are using it.
I'm only guessing since you haven't shown us the code that's going wrong, but I think you're using the function name as a return value. This is a bad habit that Visual Basic teaches people -- nearly every other language uses return instead, which is what Python does. In Python, you would use a variable (I like to use result) to calculate what you'll return, then put return result at the end of your function. E.g.,
def addTwoNumbers(one, two):
# addTwoNumbers = one + two # Wrong!
result = one + two
return result
In a simple function like this, you could just write return one + two, but in more complicated functions, it's useful to use a variable to calculate the result, then return it at the end. So that's what I showed in this example.
I'm fairly new to python and understand that recursion is an important concept to grasp. I've been dabbling with various scripts to exercise my knowledge and have come up with the following script to simulate a lottery draw, where you simply draw six from 49 numbers and compare them with another six to see if you've won. I'm struggling though with the recursive function taking the value of another function.
I'm sure it's going to be straightforwardish, but cannot fathom it myself.
Here's my code so far:
from random import randint
def drawSix():
six = []
while len(six) < 6:
a = randint(1,49)
if a not in six:
six.append(a)
return sorted(six)
def lottery(draw,ticket):
if draw == ticket:
return 'win'
return lottery(drawSix(),drawSix())
I call the function with lottery(drawSix(),drawSix())
and get the following recursively.
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
lottery(drawSix(),drawSix())
File "/Users/johnhopkins/Desktop/lottery.py", line 14, in lottery
return lottery(drawSix(),drawSix())
def lottery(draw,ticket):
if draw == ticket:
return 'win'
return lottery(drawSix(),drawSix())
The odds of you actually generating two identical tickets are quite large, well over 1000 which is the maximum stack size of Python.
You need to either do this iteratively to avoid blowing your stack.
def lottery(draw,ticket):
while draw != ticket:
draw, ticket = drawSix(), drawSix()
return "win"
Note this has a very ugly O(n) of O(inf) you could end up running this forever if you were unlucky and still not finding a winning pair
Well, your question has has been answered, but I would suggest changing your drawSix function. As it is now, it could technically run forever. random has a sample method to generate unique numbers.
def drawSix():
return sorted(random.sample(range(1, 50), 6))
Yes - the lottery function will keep on calling itself, each time putting a new version of itself onto the call stack, going deeper and deeper into itself until there are two matching numbers.
This can take a long time, and Python will eventually say "oi! stop it!" and crash.
Some programming languages have a feature called 'tail call optimisation', which means if you try to return the result of the same function, instead of making a new call to the function inside the current one, it simply replaces itself in the stack.
Python doesn't do that.
def lottery():
while (drawSix() != drawSix()):
continue
return 'win!'
will have the same effect as your recursive version, but won't die with recursion errors.
You have not made any programming mistakes. However, the probility of winning the lottery is very small, so you need to generate a lot. Easy recursion add something to the stack.
Number of lotto tickets can be found by the formula for combinations with repetition:
(49+6-1)! / (6! * (49-1)!) = 25827165
This is a lot... Decrease the number 6 or 49, add some debugging lines and you'll see that the code works fine!
The below snippet of code keeps returning a "NoneType isn't iterable" error. Why doesn't the if statement catch this?
inset = set()
for x in node.contacted:
print type(x)
if x.is_converted() is True:
nset.add(x)
if x.contacted is None:
memotable[node.gen][node.genind] = nset
else:
nset.union(self.legacy(x, memotable))
memotable[node.gen][node.genind] = nset
Full traceback as requested:
Traceback (most recent call last):
File "F:\Dropbox\CS\a4\skeleton\trialtest.py", line 142, in
test_legacy_and_frac()
File "F:\Dropbox\CS\a4\skeleton\trialtest.py", line 125, in
test_legacy_and_frac
cunittest2.assert_equals(set([n10,n12,n21]), t.legacy(n00,mtable))
File "F:\Dropbox\CS\a4\skeleton\trial.py", line 138, in legacy
nset.union(self.legacy(x, memotable))
File "F:\Dropbox\CS\a4\skeleton\trial.py", line 138, in legacy
nset.union(self.legacy(x, memotable))
TypeError: 'NoneType' object is not iterable
The if statement guarantees that x.contacted isn't None.
But x.contacted isn't what you're trying to iterate or index, so it isn't guarding anything.
There's no reason memotable or memotable[node.gen] can't be None even though x.contacted is something else. For that matter, we have no idea of what the code inside self.legacy(x, memotable) does—maybe it tries to iterate x, or other_table[x], or who knows what, any of which could be None.
This is why you need to look at the entire traceback, not just the error string. It will tell you exactly which statement failed, and why.
And now that you've pasted the traceback:
File "F:\Dropbox\CS\a4\skeleton\trial.py", line 138, in legacy nset.union(self.legacy(x, memotable))
Yep, it's something that happens inside that self.legacy line, and it has absolutely nothing to do with x.contacted. The problem is almost certainly that your self.legacy method is returning None, so you're doing nset.union(None).
Again, whether x.contacted is or is not None is completely irrelevant here, so your check doesn't guard you here.
If you want us to debug the problem in that function, you will have to give us the code to that function, instead of code that has nothing to do with the error. Maybe it's something silly, like doing a + b instead of return a + b at the end, or maybe it's some deep logic error, but there's really no way we can guess.
Check the value of memotable and memotable[node.gen] as it can not be said to guaranteed that they are not None if x.contacted is not None (without the code).
If you mention the values of the variables here and Post the Full Traceback, we may be able to point out the problem more precisely.
The exception occurs because the function call self.legacy(x, memotable) returns None.
The traceback indicates the error occurs in nset.union(self.legacy(x, memotable)), and set.union() raises that exception when its argument is None. (I'm assuming nset is a set. Your code defines inset = set(), but does not show where nset comes from)
>>> set().union(None)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'NoneType' object is not iterable
[SearchAgent] using function depthFirstSearch
[SearchAgent] using problem type PositionSearchProblem
Path found with total cost of 999999 in 0.0 seconds
Search nodes expanded: 1
Traceback (most recent call last):
File "C:\Documents and Settings\vpn\My Documents\Aptana Studio 3 Workspace\Project 1 - Search\pacman.py", line 672, in <module>
runGames( **args )
File "C:\Documents and Settings\vpn\My Documents\Aptana Studio 3 Workspace\Project 1 - Search\pacman.py", line 638, in runGames
game.run()
File "C:\Documents and Settings\vpn\My Documents\Aptana Studio 3 Workspace\Project 1 - Search\game.py", line 662, in run
action = agent.getAction(observation)
File "C:\Documents and Settings\vpn\My Documents\Aptana Studio 3 Workspace\Project 1 - Search\searchAgents.py", line 121, in getAction
if i < len(self.actions):
TypeError: object of type 'NoneType' has no len()
m working on a project in which i have to test my pacman agent to reach to its destination in less possible space and time complexity by applying DFS(Depth First Algorithm)
My code for it is
stack = util.Stack()
explored = list()
start = problem.getStartState()
for item in problem.getSuccessors(start):
state = item[0]
path = list()
path.append(item[1])
stateInfo = (state, path)
stack.push(stateInfo)
explored.append(start)
while stack.isEmpty():
state = stack.pop()
if problem.isGoalState(state[0]):
return state[1]
for states in problem.getSuccessor(state[0]):
newstate = states[0]
newpath = list(state[1])
newpath.append(states[1])
newstateInfo = (newstate, newpath)
stack.push(newstateInfo)
explored.append(state[0])
What should i suppose to do now.. my pacman agent get stuck to its starting position in east dirction opposite to its destination.
The supporting files to run the agent is mentioned in https://www.edx.org/courses/BerkeleyX/CS188.1x/2012_Fall/courseware/Week_2/Project_1_Search/
I think I know what is going on (though I can't be certain given the limited amount of code in the question).
My guess is that the code you've posted is getting called to set up the variable self.actions where you're getting an error. The error is happening because you're getting None returned from the function, rather than the list you expect.
The underlying bug is that your main loop has it's test backwards. You want while not stack.isEmpty(), rather than what you have. Because you've just pushed several values onto the stack, the loop as written exits immediately. After the loop you reach the end of the function, which is equivalent to returning None in Python. That None is causing the exception later.
Even if you fix the broken loop, falling off the end of the function can happen anyway if a path cannot be found to the goal state. I suggest adding code to detect this, and respond appropriately. You could raise an exception (since it shouldn't happen in normal situations), or maybe return an empty list.
There's another issue where you're not checking if a newly visited state has already been explored. This could lead to an infinite loop, as you search from one state to a neighbor and then back. A set will also be better than a list for explored. You can check it with if state in explored (which also works on lists, but less efficiently).
As a side issue, some of your variables are very poorly named. state different types at different times, and having a second variable states makes it even more confusing, especially with indexing thrown in.
I suggest unpacking the tuples you pushed onto the stack with the code state, path = stack.pop(), which will solve part of the issue. Then just rename states to something else (or perhaps unpack it too, with something like for neighbor, direction in problem.getSuccessor(state)) and you'll be good to go.
You can also save a few lines of code by pushing the start state to your stack, rather than doing an extra loop over its neighbors in the setup code.