【问题标题】:TypeError - Can't convert 'User' object to str implicitlyTypeError - 无法将“用户”对象隐式转换为 str
【发布时间】:2018-12-07 19:15:02
【问题描述】:

我有一个在 python 2.7 上运行良好的代码,但后来我迁移到 python 3.5 并且它不再工作了,我收到了一个错误。 代码如下:

def gen_cert(keyname, certname, password, username):
cmd = [
    'openssl', 'pkcs12', '-name', username, '-inkey', tempdirname + keyname,
    '-in', tempdirname + certname, '-export', '-out',
    dirname + username + '.p12', '-password', 'pass:' + password
]
s = subprocess.Popen(cmd, shell=False)
out, err = s.communicate('\n'.encode())

错误是-Can't convert 'User' object to str implicitly

错误是由于这个dirname + username + '.p12'

这里是局部变量:

| Variable | Value           |
______________________________
| certname |'w0ui8t9mkg.pem' |
| keyname  |'7g89utc1it.pem' |
| password |'bo02qm99ui'     |
| username |<User: abcuser>|

这是调用上述函数的函数:

def generate_user_certificate(self, request, queryset):
    check_folders(request)
    UsersList = []

    for qs in queryset:
        username = qs.username
        keyname = random_name('.pem')
        certname = random_name('.pem')
        password = random_name('')
        gen_cert(keyname, certname, password, username)

        UsersList.append(username)

    # Displaying success message for certificate generation
    allusers = ', '.join(UsersList)
    messages.success(
        request,
        "Certificates for users: " + allusers + " generated successfully.")

我在allusers = ', '.join(UsersList) 中也遇到了错误 上面写着sequence item 0: expected str instance, User found

如何解决? 我正在使用 django 2.0

【问题讨论】:

  • 我猜用户名是一个用户对象?
  • 显示username的代码
  • 是的,用户名是一个用户对象。
  • 您能否包含调用gen_cert() 函数的代码?如果可能的话,可能还有User 类的代码。
  • @RishabhChaudhary 我更新了我对 Django 2.0 的回答,尽管在您的代码中查看 gen_cert() 被调用的位置仍然会有所帮助。它是 python,所以我知道这不是编译时错误;)

标签: python python-3.x typeerror


【解决方案1】:

简要建议: 发生的事情是 qs.username 指向一个 User 对象,但您希望它指向一个字符串(即,该 User 对象的用户名)。除了以下修复之外,我建议您尝试更改查询集中的键。现在你有一个键 username 指向一个不是用户名的东西,这是令人困惑的(尽管你不需要这样做来让你的代码工作;这只是一个风格建议)。

如何解决错误: 假设您使用默认的 Django.contrib.auth 用户模型,您可以使用User.get_username() 访问用户名。我之前推荐的str(username) 方法也可以工作,因为它调用User 对象上的__str__() 函数,该函数默认返回用户名。最好在调用gen_cert() 时调用任一方法,方法是将username 变量设置为:

username = qs.username.get_username()

username = str(qs.username)

对于您关于allusers = ', '.join(UsersList) 的第二个问题,我认为您遇到了同样的问题,一旦username 变量实际指向一个字符串,而不是User 对象,该问题就会得到解决。

【讨论】:

  • 根据您的建议,我使用了str(username),它可以工作。但我在这里用过:for qs in queryset: username = str(qs.username) keyname = random_name('.pem') certname = random_name('.pem') password = random_name('') gen_cert(keyname, certname, password, username) 这甚至解决了第二个错误。
  • 啊,好吧,所以我猜str(User) 确实返回了User 对象的用户名。我很高兴知道您已经解决了这些错误 :) 我要补充的一件小事是,现在,您的变量 qs.username,(即与 queryset 中的每个元素关联的 username 条目) 确实指向一个 User 对象,严格来说它不是 username (用户名是一个字符串,它只是每个 User 对象具有的一个属性)。这只是一个风格问题,但如果我正在编写这段代码,我会担心如果我的密钥 username 指向一个 User 对象,我会感到困惑。
  • @RishabhChaudhary 我更新了我的答案以反映您对问题所做的更改(以防将来有人引用此问题)。如果您认为我的回答正确解决了您的问题,请将其标记为已接受,这会将这个问题标记为已解决并帮助未来的用户(并给我代表点:))。如果没有,请随时回复这些 cmets。
【解决方案2】:

这看起来像是数据类型错误或问题。您视为 String 类型的项目实际上存储为 Object 类型。找出数据类型,然后适当地处理它。您需要转换类型。将您的用户名转换为字符串,然后再将其读入代码中的 cmd 行

我认为需要对这行代码进行更改: cmd = ['这里有一些内容', dirname + username + '.p12']

class str(object='')
class str(object=b'', encoding='utf-8', errors='strict')

返回对象的字符串版本。如果未提供对象,则返回空字符串。否则,str() 的行为取决于是否给出了编码或错误,如下所示。

如果既没有给出编码也没有给出错误,str(object) 返回 object.str(),它是 object 的“非正式”或可很好打印的字符串表示。对于字符串对象,这是字符串本身。如果 object 没有 str() 方法,则 str() 回退到返回 repr(object)。

如果给出了编码或错误中的至少一个,则对象应该是类似字节的对象(例如字节或字节数组)。在这种情况下,如果 object 是 bytes(或 bytearray)对象,则 str(bytes, encoding, errors) 等价于 bytes.decode(encoding, errors)。否则,在调用 bytes.decode() 之前获取缓冲区对象底层的字节对象。有关缓冲区对象的信息,请参阅二进制序列类型 — 字节、字节数组、内存视图和缓冲区协议。

在没有编码或错误参数的情况下将字节对象传递给 str() 属于返回非正式字符串表示的第一种情况(另请参见 Python 的 -b 命令行选项)。例如:

str(b'Zoot!')
"b'Zoot!'"

有关 str 类及其方法的更多信息,请参阅下面的文本序列类型 — str 和字符串方法部分。要输出格式化字符串,请参阅格式化字符串文字和格式化字符串语法部分。此外,请参阅文本处理服务部分。

str.format(*args, **kwargs)

执行字符串格式化操作。调用此方法的字符串可以包含由大括号 {} 分隔的文字文本或替换字段。每个替换字段都包含位置参数的数字索引或关键字参数的名称。返回字符串的副本,其中每个替换字段都替换为相应参数的字符串值。

"The sum of 1 + 2 is {0}".format(1+2)
'The sum of 1 + 2 is 3'

以下 3 页的信息应该会有所帮助:

来自 Sebastian Raschka 的网站:

统一码 Python 2 有 ASCII str() 类型,单独的 unicode(),但没有字节类型。 (在您的情况下,您曾经用作字符串,现在被视为对象。)

Python 3,具有 Unicode (utf-8) 字符串和 2 个字节类:字节和字节数组。

Python 2:

In:  print 'they are really' + b' the same'
Out: they are really the same

Python 3:

IN:  print('and Python', python_version(), end="")
IN:  print(' also has', type(bytearray(b'bytearrays')))
OUT: and Python 3.4.1 also has <class 'bytearray'>

'note that we cannot add a string' + b'bytes for data'


 ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)

    <ipython-input-13-d3e8942ccf81> in <module>()
    ----> 1 'note that we cannot add a string' + b'bytes for data'



    TypeError: Can't convert 'bytes' object to str implicitly

来自 geeksforgeeks:

Unicode:

在 Python 2 中,隐式 str 类型是 ASCII。但是在 Python 3.x 中隐式 str 类型是 Unicode。

print(type('default string '))
print(type(b'string with b '))

'''
Output in Python 2.x (Bytes is same as str)
<type 'str'>
<type 'str'>

Output in Python 3.x (Bytes and str are different)
<class 'str'>
<class 'bytes'>
'''

【讨论】:

  • 如果username是一个字节数组,那么我认为它可以被转换为一个字符串:username = username.decode('ASCII')
【解决方案3】:

您正在尝试连接两个对象,但其中至少一个不是 str 类型,为此,您应该实现 User 类的 __str__ 方法,在该方法中返回代表您的类的值,以便你可以按照你想要的方式连接它dirname + str(username)它调用username.__str__方法

【讨论】:

    【解决方案4】:

    更改此设置后,两个错误均已解决:

    for qs in queryset:
            username = qs.username
    

    到这里:

    for qs in queryset:
            username = str(qs.username)
    

    这不是username = qs.username 使用username = str(qs.username) 这将username 转换为str,因此在调用gen_cert 函数后不需要转换。

    所以这有助于解决这两个错误。

    感谢大家的回答和建议,他们帮助了很多:)

    【讨论】:

      猜你喜欢
      • 2017-08-31
      • 2012-11-19
      • 2015-12-23
      • 1970-01-01
      • 1970-01-01
      • 2015-01-18
      • 2018-09-12
      • 1970-01-01
      相关资源
      最近更新 更多