Because under the hood the shelve module uses one of bsddb, gdbm or dbm for storage, and they support only string keys.
You're right that you can pickle a dict that uses other objects as keys, but then when one key changes, you have to flush the whole storage. By using a key-value database like those, only the changed values are flushed.