竞争条件符合 Python

Race condition in line of Python

我有一个有趣的问题。我 - 为了狗屎和傻笑 - 试图真正快速地编写一个程序。我把它减少到 2 行,但它有一个竞争条件,我不知道为什么。这是它的要点:

imports...
...[setattr(__main__, 'f', [1, 2, ..]), reduce(...random.choice(f)...)][1]...

每隔一段时间,就会产生如下异常。但不总是。那是我的问题。 我怀疑不能保证执行顺序,特别是因为我使用了列表技巧——我假设解释器可以预测 setattr() returns None 并且知道我只选择列表中的第二个东西,所以它将实际的 setattr() 推迟到以后。但这只是有时发生。有任何想法吗? CPython 是否会自动线程化某些东西,例如 map、filter、reduce 调用?

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

我试过修改 globals() 和 vars() 代替使用 setattr(),但这似乎没有帮助(相同的异常序列)。

这是实际代码:

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]))

好奇的话:这是读入一个文本文件,生成马尔可夫模型,吐出一句话。

random.choice()

嗯,当然这是不确定的。如果你非常小心,你可以将伪随机数生成器的种子设置为某个常量,并希望每次都能生成相同的序列。它很有可能会奏效。

random.seed(42); ...

好吧,这是实际发生的事情:在我的句子生成中,我有时会点击文件中的最后一个词(在某些情况下,根据文件,它没有可能的后继状态)。因此,在这种情况下,我试图从一个空列表中进行选择。