Seemingly random error appearing when executing code in Python 3.3 - python

Below is a portion of code from a program I have written that is by all means pretty basic.
pc1 = random.choice(cards)
cca1 = random.choice(cards)
while (pc1 == cca1):
cca1 = random.choice(cards)
ccb1 = random.choice(cards)
while (pc1 == ccb1) or (cca1 == ccb1):
ccb1 = random.choice(cards)
pc1, cca1 and ccb1 are just names of variables, shortened for ease of use. What this portion of code does is try to take 3 entries from a dictionary named cards. It uses the while functions to ensure that the chosen cards are not the same; they will always be different.
This goes on until I have 9 unique variables from my dictionary of 52, and it works fine except for sometimes producing the following error:
Traceback (most recent call last):
File "C:\Python33\Programs\Poker\1.0.py", line 231, in <module>
ccc2 = random.choice(cards)
File "C:\Python33\lib\random.py", line 252, in choice
return seq[i]
KeyError: 0
The variable in the error above (ccc2) is just a continuation of the previously shown code, and the variable supposedly causing the error changes every time.
The error only occurs sometimes (sometimes the program runs fine, other times it shows the error), and the line it occurred on also changes with every appearance.
I understand my code is inefficient but I'm really just looking to stop this error, and maybe some useful ideas/hints on how to improve.
Once again; does what its supposed to but unidentifiably returns the error mentioned at seemingly random times with a seemingly random site of cause.
Thanks in advance!

The way random.choice works is designed for sequences, not mappings. It picks indices, so will sometimes try cards[0], which evidently isn't a valid key. The reason that the error appears random is, of course, because it depends on the value picked by random!
You can fix this by explicitly choosing from a sequence:
random.choice(list(cards))
To improve your code more generally, note that random also includes sample:
rcards = random.sample(list(cards), 3) # pick three random cards
Note that in both cases, we randomly choose keys from the dictionary.

Related

Commenting print() breaks the Python code

I was faced with a very strange problem.
With print() this code works.
def max_pairwise_product(numbers):
max_1 = max(numbers)
numbers.remove(max_1)
max_2 = max(numbers)
return max_1 * max_2
if __name__ == '__main__':
input_n = int(input())
print() # <- comment of this line breaks the code
input_numbers = [int(x) for x in input().split()]
print(max_pairwise_product(input_numbers))
If I comment or delete the 10-th line with print() I got an error:
Traceback (most recent call last):
File "C:\Users\...\maximum_pairwise_product_fast.py", line 12, in <module>
print(max_pairwise_product(input_numbers))
File "C:\Users\...\maximum_pairwise_product_fast.py", line 2, in max_pairwise_product
max_1 = max(numbers)
ValueError: max() arg is an empty sequence*
Process finished with exit code 1
I use Python 3.9. PyCharm.
I tried to launch with different virtual environments with Python 3.8 and 3.10 – the same error.
When I launch in Jupyter and Colab – it is fane – no error.
There are no issues with any other Python script. I used the installation for several months and there was nothing strange.
It is so strange that I have no idea. Could you please help me?
Try checking if your python interpreter is working correctly and is the latest python
It might fix it or there's probably a problem with your ide.
Thank you all for helping to refer me in the right direction.
The reason for the error was a bug in PyCharm. It sent not was typed. The issue disappeared after the PyCharm update from version 2022.1.1 to 2022.1.2.
Back in 2018 or so, I found a similar strange issue in a Python program I downloaded that solved Rubik's cubes. Basically, the program ran just fine under Linux, but under Windows it was erroring out at a certain line that looked fine.
I ran "pyflakes" on that program, but pyflakes reported that nothing was wrong. Odd.
The line that supposedly contained the error was a list comprehension, much like your line here:
input_numbers = [int(x) for x in input().split()]
I replaced the list comprehension with a normal for-loop, and then the code ran fine with no errors. Basically, if I were to rewrite your line, I would replace it with the following four lines:
input_numbers = []
for x in input().split():
input_numbers.append(int(x))
assert input_numbers, "input_numbers is empty!"
I have no idea why the error was happening in the first place, and only on Windows. (The version of Python3 I was using certainly supported list comprehensions; I checked.) But once I replaced the list comprehensions with a for-loop, the code worked.
So my advice is to replace your list-comprehension with a for-loop and see if that solves anything.
I don't know if that will work, but it's worth a shot, as it seems that your input_numbers list is not actually being populated before it's passed to max_pairwise_product().
You might even try putting the assert statement:
assert input_numbers, "input_numbers is empty!"
after the list comprehension to verify that input_numbers is truly being populated. If it's not, then you at least have narrowed down your problem, and will now have to figure out why it's not being populated.
P.S. I'm curious: Which operating system(s) does the error happen on?
P.P.S. I recommend adding input text to your input() calls (such as input("Type some space-separated numbers: "), even if just for posting here. Otherwise, when stackoverflow users run your code, it looks like your code is hanging.

can not find the reason for 'name not defined' in python code

Excuse the debugging question, new to coding in general. Cannot understand why my code suddenly wont run.
I have checked for typos which seems to not be my problem.
filepath = '/proper_noun.txt'
def pluralize(word):
proper_nouns = [line.strip() for line in open (filepath)]
for item in proper_nouns: ### print out the list once.
if (item==[-1]):
break;
currently working in google colab.
At this point, I'm just trying to return the items from 'proper_nouns' into a list to get the ball rolling. Any ideas?
print (proper_nouns)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-29-c6832e0493e8> in <module>()
----> 1 print (proper_nouns)
NameError: name 'proper_nouns' is not define
Thanks guys. I hope this question follows SOF etiquette
Since you are working on Google Colab, my guesss is that you accidentally don't run the code from the beginning (from example if you selected the code starting from for item in proper_nouns: and only run the selected part, or if you split your program in different cells), and therefore proper_nouns is not defined yet.
Please make sure you run everything and tell us if that was it.
EDIT: I just thought of another option: is the line print(proper_nouns) in the pluralize function? If not, the scope of proper_nouns being the function, it's normal that it is not defined outside of the function. To access it from the outside, you must either declare it outside the function, or return it.

list() gives TypeError: 'Node' object is not callable - BUT ONLY AFTER SOME CODES

I hope this is an easy one for you guys.
This is my script, for Nuke.
selNodes = nuke.selectedNodes()
for list in selNodes:
if list.Class() == 'Read':
layerArray = []
# Get the list of layers and make unique using set
for chanList in list.channels():
channelLayer = chanList.split('.')
layerArray.append(channelLayer[0])
print list(set(layerArray))
It gives an error:
Traceback (most recent call last):
File "<string>", line 11, in <module>
TypeError: 'Node' object is not callable
So I tried a simpler code of the same nature:
a = [1, 1]
print list(set(a))
And it didn't work. Same error message. Now here's the strange thing: I opened up a new Nuke and ran the simpler codes again, it worked. I couldn't understand why, but I was happy. So I put in my original codes and ran it, error message. I deleted them, the editor is now clean. And ran the simpler code again, error message!!
Which means that a working code can be rendered failure after I pasted and deleted something else!
Can anyone shed some light on this issue? Nuke is a very established software I don't know if it's a software bug.
It is because, you are using list as the loop variable, which hides the builtin function list. You are using that function in
print list(set(layerArray))
The loop variables are leaked even when the loop is over, check this program to understand better
for i in range(10):
pass
print(i)
This will print 9. It means that, i is still available in the program even after the loop is over. The case in your program, after iterating over the selNodes, list variable has the last variable. And you are trying to call that like a function when you say
print list(set(layerArray))
That's why it fails. There are two ways to fix this.
Just change the loop variable to something else.
Use del list when the loop is over. Just pretend that I didn't suggest this. This is NOT recommended. Just change the loop variable to something else.

Python something resets my random seed

My question is the exact opposite of this one.
This is an excerpt from my test file
f1 = open('seed1234','r')
f2 = open('seed7883','r')
s1 = eval(f1.read())
s2 = eval(f2.read())
f1.close()
f2.close()
####
test_sampler1.random_inst.setstate(s1)
out1 = test_sampler1.run()
self.assertEqual(out1,self.out1_regress) # this is fine and passes
test_sampler2.random_inst.setstate(s2)
out2 = test_sampler2.run()
self.assertEqual(out2,self.out2_regress) # this FAILS
Some info -
test_sampler1 and test_sampler2 are 2 object from a class that performs some stochastic sampling. The class has an attribute random_inst which is an object of type random.Random(). The file seed1234 contains a TestSampler's random_inst's state as returned by random.getstate() when it was given a seed of 1234 and you can guess what seed7883 is. What I did was I created a TestSampler in the terminal, gave it a random seed of 1234, acquired the state with rand_inst.getstate() and save it to a file. I then recreate the regression test and I always get the same output.
HOWEVER
The same procedure as above doesn't work for test_sampler2 - whatever I do not get the same random sequence of numbers. I am using python's random module and I am not importing it anywhere else, but I do use numpy in some places (but not numpy.random).
The only difference between test_sampler1 and test_sampler2 is that they are created from 2 different files. I know this is a big deal and it is totally dependent on the code I wrote but I also can't simply paste ~800 lines of code here, I am merely looking for some general idea of what I might be messing up...
What might be scrambling the state of test_sampler2's random number generator?
Solution
There were 2 separate issues with my code:
1
My script is a command line script and after I refactored it to use python's optparse library I found out that I was setting the seed for my sampler using something like seed = sys.argv[1] which meant that I was setting the seed to be a str, not an int - seed can take any hashable object and I found it the hard way. This explains why I would get 2 different sequences if I used the same seed - one if I run my script from the command line with sth like python sample 1234 #seed is 1234 and from my unit_tests.py file when I would create an object instance like test_sampler1 = TestSampler(seed=1234).
2
I have a function for discrete distribution sampling which I borrowed from here (look at the accepted answer). The code there was missing something fundamental: it was still non-deterministic in the sense that if you give it the same values and probabilities array, but transformed by a permutation (say values ['a','b'] and probs [0.1,0.9] and values ['b','a'] and probabilities [0.9,0.1]) and the seed is set and you will get the same random sample, say 0.3, by the PRNG, but since the intervals for your probabilities are different, in one case you'll get a b and in one an a. To fix it, I just zipped the values and probabilities together, sorted by probability and tadaa - I now always get the same probability intervals.
After fixing both issues the code worked as expected i.e. out2 started behaving deterministically.
The only thing (apart from an internal Python bug) that can change the state of a random.Random instance is calling methods on that instance. So the problem lies in something you haven't shown us. Here's a little test program:
from random import Random
r1 = Random()
r2 = Random()
for _ in range(100):
r1.random()
for _ in range(200):
r2.random()
r1state = r1.getstate()
r2state = r2.getstate()
with open("r1state", "w") as f:
print >> f, r1state
with open("r2state", "w") as f:
print >> f, r2state
for _ in range(100):
with open("r1state") as f:
r1.setstate(eval(f.read()))
with open("r2state") as f:
r2.setstate(eval(f.read()))
assert r1state == r1.getstate()
assert r2state == r2.getstate()
I haven't run that all day, but I bet I could and never see a failing assert ;-)
BTW, it's certainly more common to use pickle for this kind of thing, but it's not going to solve your real problem. The problem is not in getting or setting the state. The problem is that something you haven't yet found is calling methods on your random.Random instance(s).
While it's a major pain in the butt to do so, you could try adding print statements to random.py to find out what's doing it. There are cleverer ways to do that, but better to keep it dirt simple so that you don't end up actually debugging the debugging code.

The Python assignment operator, function definitions, and variable definitions

Well... I was having a terrible time getting part of my code working, but I rearranged things and it suddenly started working correctly. Not sure what I did to be honest, so I guess that will be the subject of this question. I'm building a simple text-based card game that uses decks uploaded from two .txt files. It's aimed at Magic: the Gathering, but would probably work with others if people got creative with it. To provide a rough overview, here is how things are arranged:
import random
def shuffle(board1):
def game():
#board=[[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]]
#performs most of the actions relating to the game
board[0]=20
board[10]=20
def gameboard(board2):
#displays game board
def draw(board3, numcards, player):
#draws cards
def upload(deckname):
#uploads cards from file
def life(board4):
#asks about which player the life total is changing on, by how much, etc.
#and then does it
def maketoken(board5):
#creates tokens, counters, etc. based on user input
def move(board5):
#accepts user input and moves cards from zone to zone
def play(board6):
#handles casting spells, using abilities, triggered abilities, etc.
#main body of program is below function definitions
board=[[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]]
deckname1=input("\nWhat is the name of deck 1?")
deckname2=input("\nWhat is the name of deck 2?")
deck1=upload(deckname1)
deck2=uplaod(deckname2)
board[1]=deck1
board[11]=deck2
#this is where a lot of the other variables get set
game()
(note: most of the code has been removed for brevity and prettiness, as my code is pretty ugly)
I have a college-level C++ background, and just recently decided to pick up ye olde keyboard for the heck of it, so the assignment operator (=) not working the way I expect is driving me CRAZY. Therefore, I was also wondering if there was a way to get the functionality of the C++ '=' in Python, since I upload the decks from .txt files, and want to be through with the upload() function as soon as that's done (I use deck1=upload(deckname) (same for deck2). I want to use 'deck1' and 'deck2' to refill the decks after each game, but if I understand how '=' works in python, entering board[1]=deck1 means board[1] will point to the storage area of deck1 and changes to board[1] will change deck1, BUT I DON'T WANT THAT... GRRRR!!!!!!11). I'm sure there's a solution out there somewhere since it's making me nutty, but I haven't been able to find it. Thanks!!!
edit: This was the error I received when things were set up this way:
Traceback (most recent call last):
File "C:\Users\inventor487\Desktop\simplepy.py", line 444, in <module>
game()
File "C:\Users\inventor487\Desktop\simplepy.py", line 114, in game
board[1]=deck1
UnboundLocalError: local variable 'board' referenced before assignment
Summary:
Do I need to pass board to the game() function, even if it's set up as a global variable (or at least I thought it was)? Everything seems to work fine when I assign it inside the game() function (commented out to show this). (edit: nevermind... I'm an idiot.)
Does assigning part of board to a value inside game() make it a local variable (e.g. where I have board[0]=20)? (edit: yes, it does apparently...)
As you've discovered, the = operator in Python doesn't make a copy of an object like it does in C++ for example. If you want to make a copy to store in another variable you have to be explicit about it.
board[1] = deck1[:] # the slicing operator copies a subset or the whole list
A more general method is to use the copy module
import copy
board[1] = copy.copy(deck1)
board[1] = copy.deepcopy(deck1)
edit: a class solves all of this very easily, and much more cleanly. Having a separate variable for each zone, etc. makes everything a lot smoother. Thanks for the help, though guys. Much appreciated.

Categories