If you replace the line
val1 = dict(fooblah=[], xy=[])
with
exec "val1 = dict(fooblah=[], xy=[])"
Then the statements pass again.
Why?? The answer lies deep inside cPickle's secrets. It has an optimization that looks like if some objects have a reference count less than 2, and avoids several bytes in this case (usually used to detect loops or multiple occurrences of the same, possibly large string). These are the string objects "fooblah" and "xy". In the case of exec or when starting interactively, by the time you compile, the only links left for the lines are in the dictionary; the control counter is 1, so cPickle avoids several bytes. But if you write the example as a module, then the module is still alive at that time, and it retains another link to the strings used as constants.
EDIT to clarify: the second time we pickled, we will analyze the dictionary, which always has fresh keys coming from the counter of loose links 1. Thus, the statement is transmitted if and only if the keys, where there is also a reference counter 1 in the first time.
source share