首页 > 解决方案 > Python -- TypeError: POST 数据应该是字节、字节的可迭代或文件对象。它不能是 str 类型

问题描述

我正在为一些 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 类型。

请建议可以做什么?

谢谢

标签: pythonpython-3.xpython-2.7python-requestsurllib

解决方案


您需要确保将所有内容正确转换为字节,如评论中所述,使用请求比使用 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

推荐阅读