【问题标题】:Python -- TypeError: POST data should be bytes, an iterable of bytes, or a file object. It cannot be of type strPython -- TypeError: POST data 应该是字节、字节的可迭代或文件对象。它不能是 str 类型
【发布时间】:2021-09-22 07:34:12
【问题描述】:

我正在为一些 webhook url 编写 python 代码。 早些时候,代码在 python 2.7 上工作,必须更新到 python 3 Python 2 到 3 的转换是使用 2to3 完成的。 Python 2 代码:

def send_webhook_request(url, body, user_agent=None):
    if url is None:
        print >> sys.stderr, "ERROR No URL provided"
        return False
    print >> sys.stderr, "INFO Sending POST request to url=%s with size=%d bytes payload" % (url, len(body))
    print >> sys.stderr, "DEBUG Body: %s" % body
    try:
        user="USER"
        password="PASSWORD"
        credentials = (user + ':' + password).encode('utf-8')
        base64_encoded_credentials = base64.b64encode(credentials).decode('utf-8')
        headers = {'Authorization': 'Basic ' + base64_encoded_credentials, "Content-Type": "application/json", 'User-Agent': user_agent}
        #req = urllib.urlopen(url, body, headers)
        req = urllib2.Request(url, body, headers)
        res = urllib2.urlopen(req)
        response = res.read()
        #res = urllib2.read()
        if 200 <= res.code < 300:
            print >> sys.stderr, "INFO Webhook receiver responded with HTTP status=%d" % res.code
            return response
        else:
            print >> sys.stderr, "ERROR Webhook receiver responded with HTTP status=%d" % res.code
            return False
    except urllib2.HTTPError, e:
        print >> sys.stderr, "ERROR Error sending webhook request: %s" % e
    except urllib2.URLError, e:
        print >> sys.stderr, "ERROR Error sending webhook request: %s" % e
    except ValueError, e:
        print >> sys.stderr, "ERROR Invalid URL: %s" % e
    return False

Python 3 代码:编辑 1 - 将编码添加到正文。

def send_webhook_request(url, body, user_agent=None):
if url is None:
    print("ERROR No URL provided", file=sys.stderr)
    return False
print("INFO Sending POST request to url=%s with size=%d bytes payload" % (url, len(body)), file=sys.stderr)
print("DEBUG Body: %s" % body, file=sys.stderr)
try:
    user="integration.argossplunk"
    password="hv6ep_gXR+M$#8tk@e4cePYx@*Er4VD#"
    credentials = (user + ':' + password).encode('utf-8')
    base64_encoded_credentials = base64.b64encode(credentials).decode('utf-8')
    headers = {'Authorization': 'Basic ' + base64_encoded_credentials, "Content-Type": "application/json", 'User-Agent': user_agent}
    #req = urllib.urlopen(url, body, headers)
    body = body.encode()
    #body = urllib.parse.urlencode(body).encode("utf-8")
    req = urllib.request.Request(url, body, headers)
    res = urllib.request.urlopen(req)
    response = res.read()
    #res = urllib2.read()
    if 200 <= res.code < 300:
        print("INFO Webhook receiver responded with HTTP status=%d" % res.code, file=sys.stderr)
        return response
    else:
        print("ERROR Webhook receiver responded with HTTP status=%d" % res.code, file=sys.stderr)
        return False
except urllib.error.HTTPError as e:
    print("ERROR Error sending webhook request: %s" % e, file=sys.stderr)
except urllib.error.URLError as e:
    print("ERROR Error sending webhook request: %s" % e, file=sys.stderr)
except ValueError as e:
    print("ERROR Invalid URL: %s" % e, file=sys.stderr)
return False

当我调用这个函数时:

send_webhook_request(url, json.dumps(body), user_agent=user_agent)

它给了我错误 - TypeError: POST data should be bytes, an iterable of bytes, or a file object。它不能是 str 类型。

请建议可以做什么?

谢谢

【问题讨论】:

  • 请显示完整的回溯。
  • 我个人建议您从使用urllib 改为使用requests,但是对于您的代码,如果您阅读了错误消息并查阅urllib.request.Request docs.python.org/3/library/… 的文档,您'会看到数据参数必须是字节 - 但正如错误消息所说,您提供的值是str。您可以使用encode() 将 str 转换(编码)为字节,请参阅docs.python.org/3/library/…
  • @barny :我添加了编码 - 更新了编辑 1 中的代码。但是,现在我在进行更改后收到与标题相关的错误。错误:C:\ProgramData\Anaconda3\lib\http\client.py in putheader(self, header, *values) 1204 values[i] = str(one_value).encode('ascii') 1205 -> 1206 if _is_illegal_header_value( values[i]): 1207 raise ValueError('Invalid header value %r' % (values[i],)) 1208 TypeError: expected string or bytes-like object
  • 请发minimal reproducible example。强调minimal

标签: python python-3.x python-2.7 python-requests urllib


【解决方案1】:

您需要确保将所有内容正确转换为字节,如 cmets 中所述,使用请求比使用 urllib 更容易。

import base64
import urllib
from urllib import request
import sys
import json


def send_webhook_request(url, body, user_agent=None):
    if url is None:
        print("ERROR No URL provided", file=sys.stderr)
        return False
    print(
        "INFO Sending POST request to url=%s with size=%d bytes payload" %
        (url, len(body)),
        file=sys.stderr
    )
    print("DEBUG Body: %s" % body, file=sys.stderr)

    user = "integration.argossplunk"
    password = "hv6ep_gXR+M$#8tk@e4cePYx@*Er4VD#"

    # use f-strings to format Auth header correctly!
    credentials = f"{user}:{password}"
    base64_encoded_credentials = base64.b64encode(credentials.encode('utf-8'))
    headers = {
        'Authorization': f'Basic {base64_encoded_credentials.decode()}',
        "Content-Type": "application/json",
    }

    # urllib doesn't like None, so add it when given!
    if user_agent:
        headers['User-Agent'] = user_agent

    try:
        req = urllib.request.Request(url, body, headers)
        res = urllib.request.urlopen(req)
        response = res.read()
        if 200 <= res.code < 300:
            return res.code
            print(
                "INFO Webhook receiver responded with HTTP status=%d" %
                res.code,
                file=sys.stderr
            )
            return response
        else:
            print(
                "ERROR Webhook receiver responded with HTTP status=%d" %
                res.code,
                file=sys.stderr
            )
            return False
    except urllib.error.HTTPError as e:
        print("ERROR Error sending webhook request: %s" % e, file=sys.stderr)
    except urllib.error.URLError as e:
        print("ERROR Error sending webhook request: %s" % e, file=sys.stderr)
    except ValueError as e:
        print("ERROR Invalid URL: %s" % e, file=sys.stderr)
    return False


for url in ('https://xxx.yyy.zzz', 'htt://errorRaising.url'):
    params = {'param1': 'value1', 'param2': 'value2'}
    res = send_webhook_request(url, json.dumps(params).encode('utf8'))
    print(res)

输出:

INFO Sending POST request to url=... with size=40 bytes payload
DEBUG Body: b'{"param1": "value1", "param2": "value2"}'
ERROR Error sending webhook request: HTTP Error 401: Unauthorized
False
INFO Sending POST request to url=htt://errorRaising.url with size=40 bytes payload
DEBUG Body: b'{"param1": "value1", "param2": "value2"}'
ERROR Error sending webhook request: <urlopen error unknown url type: htt>
False

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-27
    • 1970-01-01
    • 2020-02-06
    • 1970-01-01
    相关资源
    最近更新 更多