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.
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.