Better Python exceptions

Use KeyError for key not found, and validate unique keys.
Better .NET exceptions

Use RuntimeBinderException for .NET key not found, and validate unique
keys.

Microsoft doesn't give us any choice about the RuntimeBinderException
type here, since the runtime binder steps in to call `TryGetMember`,
then does its own thing if a value can't be found.