General Python: Is This String a Built-in?

(I may have asked this before somewhere. If so, I don’t remember where, and don’t seem to be finding my original question. Still, if I have, then my apologies! ^^; )

In Python, is there a means of determining whether a given string (e.g. “int”) corresponds to the name of a built-in type?

By comparison, one can determine whether a string corresponds to a member of an instance by using “hasattr”, or by checking the member’s “__dict__” member, if I’m not much mistaken.

Is there some way of doing something similar for built-ins?

To explain, I’m trying to improve the security of my GameSaver module by removing "eval"s and "exec"s. Right now, an “eval” is used to reconstitute objects, running something like this:

# Given that "objType" contains a string type-name, like "int"
finalVal = eval(objType + "(newVal)")

I want to replace this, but I don’t want to create an exhaustive list of:

if objType == 'int':
    finalVal = int(newVal)
elif objType == "float":
    finalVal = float(newVal)
# etc...

Not only does that become extensive, but it doesn’t seem terribly future-proof to me.

I’m hoping that there’s an easier way, something like or analogous to this:

if objType in builtIns:
    finalVal = builtIns[objType](newVal)

Or something similarly painless, and relatively future-proof.

Any thoughts?

import builtins

if hasattr(builtins, 'int'):
    int_type = getattr(builtins, 'int')

    value = int_type(3.5)
    print(value) # 3

    assert int_type is int # does not fail

However, please note that eval is also a built-in! You may still want to have a whitelist to test against before checking this.

Ah, handy, thank you! :slight_smile:

Hmm… Would there be a problem with instead blacklisting “eval” and “exec”? Something like this:

if objType != "eval" and objType != "exec" and hasattr(builtins, objType):
    objClass = getattr(builtins, objType)
    finalVal = objClass(newVal)

I think it would be safer to create a whitelist. There are others that may have questionable security impacts (like __import__) and others may yet be added in future versions of Python.

Hmm… But would the use of a whitelist not largely defeat the object of automating this? After all, I’d be back to manually specifying each built-in type individually, and to a lack of future-proofing.

[edit]
Unless I’m missing something, it would seem that if a whitelist is required, then the following might be the simpler implementation:

# In initialisation somewhere:
builtInDict = {
"int" : int,
"float" : float,
# etc...
}

# later, when constructing objects:
if objType in builtInDict:
    objClass = builtInDict[objType]
    finalVal = objClass(newVal)

[edit 2]
I’ve realised that since a number of built-in classes are already handled by special cases (as in the case of lists, or byte-strings), there seems to be only a few that end up falling through to this general handling (most prominently: ints and floats).

As a result, I’ve decided to simply use a series of if-else statements to handle these few. It’s less flexible and future-proof, but it’s straightforward and should work.

A few classes are skipped in this (I’m not handling sets, for example). However, I think that it should be possible for devs to add support for such by nominating them to be handled as “special types” (as is currently used for Panda’s Vec* classes).