diff --git a/py/builtin.c b/py/builtin.c
index 8621b0b003964df2f28c688a06dedc26d79e3a6c..834108f1b5db03ee31f45397fd51ecf1d5600d90 100644
--- a/py/builtin.c
+++ b/py/builtin.c
@@ -452,12 +452,17 @@ STATIC inline mp_obj_t mp_load_attr_default(mp_obj_t base, qstr attr, mp_obj_t d
 }
 
 STATIC mp_obj_t mp_builtin_getattr(uint n_args, const mp_obj_t *args) {
-    assert(MP_OBJ_IS_QSTR(args[1]));
+    mp_obj_t attr = args[1];
+    if (MP_OBJ_IS_TYPE(attr, &mp_type_str)) {
+        attr = mp_obj_str_intern(attr);
+    } else if (!MP_OBJ_IS_QSTR(attr)) {
+        nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "string required"));
+    }
     mp_obj_t defval = MP_OBJ_NULL;
     if (n_args > 2) {
         defval = args[2];
     }
-    return mp_load_attr_default(args[0], MP_OBJ_QSTR_VALUE(args[1]), defval);
+    return mp_load_attr_default(args[0], MP_OBJ_QSTR_VALUE(attr), defval);
 }
 
 MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_getattr_obj, 2, 3, mp_builtin_getattr);
diff --git a/py/obj.h b/py/obj.h
index c7f0a9879e5771885fadaf2d58b6b79ed3a15080..d5ea40901cfdb684fdae7d26aff923dfb6947300 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -468,6 +468,7 @@ uint mp_obj_str_get_len(mp_obj_t self_in);
 qstr mp_obj_str_get_qstr(mp_obj_t self_in); // use this if you will anyway convert the string to a qstr
 const char *mp_obj_str_get_str(mp_obj_t self_in); // use this only if you need the string to be null terminated
 const char *mp_obj_str_get_data(mp_obj_t self_in, uint *len);
+mp_obj_t mp_obj_str_intern(mp_obj_t str);
 void mp_str_print_quoted(void (*print)(void *env, const char *fmt, ...), void *env, const byte *str_data, uint str_len);
 
 #if MICROPY_PY_BUILTINS_FLOAT
diff --git a/py/objstr.c b/py/objstr.c
index 4e70b00812b72b263427df5334a014fb9e027691..6656090c84f05db403ba96d7065d478cbbfdeb14 100644
--- a/py/objstr.c
+++ b/py/objstr.c
@@ -1751,6 +1751,11 @@ mp_obj_t mp_obj_new_str(const char* data, uint len, bool make_qstr_if_not_alread
     }
 }
 
+mp_obj_t mp_obj_str_intern(mp_obj_t str) {
+    GET_STR_DATA_LEN(str, data, len);
+    return MP_OBJ_NEW_QSTR(qstr_from_strn((const char*)data, len));
+}
+
 mp_obj_t mp_obj_new_bytes(const byte* data, uint len) {
     return mp_obj_new_str_of_type(&mp_type_bytes, data, len);
 }
diff --git a/tests/basics/getattr1.py b/tests/basics/getattr1.py
index 9a96154ca5e56034c4fa12f7d88943629596769d..59cb7e7f7a4b187be4308c68c6877491a81070fd 100644
--- a/tests/basics/getattr1.py
+++ b/tests/basics/getattr1.py
@@ -15,3 +15,4 @@ print(getattr(a, "var2"))
 print(getattr(a, "meth")(5))
 print(getattr(a, "_none_such", 123))
 print(getattr(list, "foo", 456))
+print(getattr(a, "va" + "r2"))