Cool. I believe it is a Python bug. 

```
In [6]: dct = collections.defaultdict()

In [8]: pickle.dumps(dct, protocol=2)
Out[8]: b'\x80\x02cUserString\ndefaultdict\nq\x00)Rq\x01.'

In [10]: pickle.dumps(dct, protocol=2, fix_imports=False)
Out[10]: b'\x80\x02ccollections\ndefaultdict\nq\x00)Rq\x01.'
```

The cause of error is here: http://hg.python.org/cpython/file/7272ef213b7c/Lib/_compat_pickle.py#l80

We could try fix_imports=False - it will work as soon as we don't use moved functions from stdlib directly. It should work if we e.g. import urlencode from compat.py. 

Another way is to create workarounds in compat.py (as you've done in your pull request). I believe we should also add defaultdict to UserList in this case because REVERSE_IMPORT_MAPPING relies on dict order that can vary between runs. But these workarounds are weird. Maybe it is better to patch REVERSE_IMPORT_MAPPING directly because this makes workaround more clear. 

But I hope fix_imports=False would work.