Python之——Python 3.6 Socket TypeError: a bytes-like object is required, not 'str' 错误提示

标签: Python
17人阅读 评论(0) 收藏 举报
分类:

转载请注明出处:https://blog.csdn.net/l1028386804/article/details/79957607

最近,在做Python套接字编程时,在Python2.7上的功能,迁移到Python3.6上,尼玛,各种发送、接收数据问题,查了相关的文档后,发现,Python3.6和Python2.7在套接字编程方便是有区别的,尼玛,好坑啊!特此记录,以查备忘。

发现这里python3.6和Python2.7在套接字返回值解码上有区别。

先介绍一下 python bytes和str两种类型转换的函数encode(),decode()

  • str通过encode()方法可以编码为指定的bytes
  • 反过来,如果我们从网络或磁盘上读取了字节流,那么读到的数据就是bytes。要把bytes变为str,就需要用decode()方法:

python核心编程书中的2-1例子

TCP服务器:

#coding=utf-8
#创建TCP服务器
from socket import *
from time import ctime

HOST=''
PORT=21567
BUFSIZ=1024
ADDR=(HOST,PORT)

tcpSerSock=socket(AF_INET,SOCK_STREAM) #创服务器套接字
tcpSerSock.bind(ADDR) #套接字与地址绑定
tcpSerSock.listen(5)  #监听连接,传入连接请求的最大数

while True:
    print('waiting for connection...')
    tcpCliSock,addr =tcpSerSock.accept()
    print('...connected from:',addr)

    while True:
        data =tcpCliSock.recv(BUFSIZ)
        #print('date=',data)
        if not data:
            break
        tcpCliSock.send(('[%s] %s' %(ctime(),data)))

    tcpCliSock.close()
tcpSerSock.close()

TCP客户端

#coding=utf-8

from socket import *

HOST = 'localhost' #  or 'localhost'
PORT = 21567
BUFSIZ = 1024
ADDR=(HOST,PORT)

tcpCliSock = socket(AF_INET,SOCK_STREAM)
tcpCliSock.connect(ADDR)

while True:
    data = input('> ')
    print('data=',data);
    if not data:
        break
    tcpCliSock.send(data)
    data = tcpCliSock.recv(BUFSIZ)
    if not data:
        break
    print(data)

tcpCliSock.close() 

返回的错误提示:
TypeError: a bytes-like object is required, not ‘str’
指的是18行tcpCliSock.send(data)传入的参数是应该是bytes类型,而不是str类型。

于是我去百度,发现在StackOverflow上发现有人也出现同样的问题,并一个叫Scharron的人提出了解答:

In python 3, bytes strings and unicodestrings are now two different types. Since sockets are not aware of string encodings, they are using raw bytes strings, that have a slightly differentinterface from unicode strings.

So, now, whenever you have a unicode stringthat you need to use as a byte string, you need toencode() it. And whenyou have a byte string, you need to decode it to use it as a regular(python 2.x) string.

Unicode strings are quotes enclosedstrings. Bytes strings are b”” enclosed strings

When you use client_socket.send(data),replace it by client_socket.send(data.encode()). When you get datausing data = client_socket.recv(512), replace it by data =client_socket.recv(512).decode()

于是我去查python3.6的帮助手册。

socket.send(bytes[, flags])

Send data to the socket. The socket must be connected to a remote socket. The optional flags argument has the same meaning as for recv() above. Returns the number of bytes sent. Applications are responsible for checking that all data has been sent; if only some of the data was transmitted, the application needs to attempt delivery of the remaining data. For further information on this topic, consult the Socket Programming HOWTO.

Changed in version 3.5: If the system call is interrupted and the signal handler does not raise an exception, the method now retries the system call instead of raising an InterruptedError exception (see PEP 475 for the rationale).
socket.recv(bufsize[, flags])
Receive data from the socket. The return value is a bytes object representing the data received. The maximum amount of data to be received at once is specified by bufsize. See the Unix manual page recv(2) for the meaning of the optional argument flags; it defaults to zero.

Note

For best match with hardware and network realities, the value of bufsize should be a relatively small power of 2, for example, 4096.

Changed in version 3.5: If the system call is interrupted and the signal handler does not raise an exception, the method now retries the system call instead of raising an InterruptedError exception (see PEP 475 for the rationale).

修正后:

tcp服务器

#coding=utf-8
#创建TCP服务器
from socket import *
from time import ctime

HOST=''
PORT=21567
BUFSIZ=1024
ADDR=(HOST,PORT)

tcpSerSock=socket(AF_INET,SOCK_STREAM) #创服务器套接字
tcpSerSock.bind(ADDR) #套接字与地址绑定
tcpSerSock.listen(5)  #监听连接,传入连接请求的最大数

while True:
    print('waiting for connection...')
    tcpCliSock,addr =tcpSerSock.accept()
    print('...connected from:',addr)

    while True:
        data =tcpCliSock.recv(BUFSIZ).decode()
        print('date=',data)
        if not data:
            break
        tcpCliSock.send(('[%s] %s' %(ctime(),data)).encode())

    tcpCliSock.close()
tcpSerSock.close()
tcp客户端:
#coding=utf-8

from socket import *

HOST = 'localhost' #  or 'localhost'
PORT = 21567
BUFSIZ = 1024
ADDR=(HOST,PORT)

tcpCliSock = socket(AF_INET,SOCK_STREAM)
tcpCliSock.connect(ADDR)

while True:
    data = input('> ')
    #print('data=',data);
    if not data:
        break
    tcpCliSock.send(data.encode())
    data = tcpCliSock.recv(BUFSIZ).decode()
    if not data:
        break
    print(data)

tcpCliSock.close()
socket.sendto(bytes, address)
socket.sendto(bytes, flags, address)
Send data to the socket. The socket should not be connected to a remote socket, since the destination socket is specified by address. The optional flags argument has the same meaning as for recv() above. Return the number of bytes sent. (The format of address depends on the address family — see above.)

Changed in version 3.5: If the system call is interrupted and the signal handler does not raise an exception, the method now retries the system call instead of raising an InterruptedError exception (see PEP 475 for the rationale).
socket.recvfrom(bufsize[, flags])
 Receive data from the socket. The return value is a pair (bytes, address) where bytes is a bytes object representing the data received and address is the address of the socket sending the data. See the Unix manual page recv(2) for the meaning of the optional argument flags; it defaults to zero. (The format of address depends on the address family — see above.)

同理修正udp服务器:

from socket import *
from time import ctime
HOST=''
PORT=21546
BUFSIZ=1024
ADDR=(HOST,PORT)

udpSerSock = socket(AF_INET,SOCK_DGRAM)
udpSerSock.bind(ADDR)

while True:
    print('waiting for message...')
    data,addr=udpSerSock.recvfrom(BUFSIZ)
    data=data.decode()
    udpSerSock.sendto(('[%s] %s'%(ctime(),data)).encode(),addr)
    print('...received from and returned to:',addr)

udpSerSock.close()

查看评论

【Python】第二周Python基础(下)

本周课程主要讲解Python的面向对象编程, 异常处理、模块、MySQL数据库、Python的数据库支持以及图形用户界面等技术,最后我们使用阶段案例开发了一个《飞机大战》的游戏。
  • 2018年03月16日 11:34

Python 3.5 Socket TypeError: a bytes-like object is required, not 'str' 错误提示

目前正在学习python基本语法以及计算机网络课,所以正好结合学习python网络编程,看的是《python核心编程》第三版,发现示例2-1代码返回错误… 发现这里python3.5和Python2...
  • yexiaohhjk
  • yexiaohhjk
  • 2017-03-29 16:49:57
  • 29531

python3中,socket使用send函数时出现的错误:TypeError: a bytes-like object is required, not 'str'

首先我实现的功能是:使用tcp协议实现单线程的QQ聊天 代码如下:from socket import * serversocket = socket(AF_INET, SOCK_STREAM) ...
  • wx1458451310
  • wx1458451310
  • 2017-11-21 16:31:44
  • 428

Python 3.x Error:TypeError: a bytes-like object is required, not 'str'

分析了TypeError: a bytes-like object is required, not 'str'产生的原因并给出解决办法,并列举了Python内str和bytes相互之间的转化方法。...
  • bible_reader
  • bible_reader
  • 2016-11-05 21:32:04
  • 32203

python3.5 模拟UDP客户端发送数据报文,报错:TypeError: a bytes-like object is required, not 'str'

#!/usr/bin/env python # -*- coding:utf-8 -*- import socket target_host = "127.0.0.1" target_port =...
  • welcome00
  • welcome00
  • 2017-07-16 16:15:44
  • 702

python socket send 函数 报错:TypeError: a bytes-like object is required, not 'str'

# -*- coding: utf-8 -*- ''' Created on 2017年7月28日 @author inx 实现中基本socket程序 ''' import socket host ...
  • u014770372
  • u014770372
  • 2017-07-29 00:52:02
  • 584

python中Base64编码和解码:TypeError: a bytes-like object is required, not 'str'

在目前最新版本下出现问题 F:\p>python Python 3.5.2 (v3.5.2:4def2a2901a5, Jun 25 2016, 22:18:55) [MSC v.1900 64 ...
  • dongyanwen6036
  • dongyanwen6036
  • 2017-07-31 08:51:04
  • 1618

TypeError: a bytes-like object is required, not 'str'

新手学习python,3.0中部分函数参数需要bytes,如果使用str会报告TypeError: a bytes-like object is required, not ‘str’的错误避免以上错...
  • ww0440ww
  • ww0440ww
  • 2017-01-24 19:29:45
  • 2457

Python3 Pickle报错 TypeError

最近在学一门机器学习的公开课,作业推荐使用python2.6或2.7,但因为电脑上已经装了python3,懒得换就没有改。运行示例程序时,发现pickle模块老是报错:TypeError: a byt...
  • windyyyy14
  • windyyyy14
  • 2016-07-05 21:17:03
  • 1199
    个人资料
    专栏达人 持之以恒
    等级:
    访问量: 239万+
    积分: 2万+
    排名: 209
    博客专栏
    MySQL

    文章:136篇

    阅读:314643
    Hadoop生态

    文章:149篇

    阅读:237077
    Java

    文章:162篇

    阅读:598408
    J2EE

    文章:76篇

    阅读:311792
    JVM

    文章:18篇

    阅读:55629
    Linux

    文章:85篇

    阅读:256940
    Web前端

    文章:22篇

    阅读:93968
    Mycat

    文章:20篇

    阅读:32089
    设计模式

    文章:22篇

    阅读:52776
    Memcached

    文章:9篇

    阅读:53784
    Redis

    文章:18篇

    阅读:107894
    Netty

    文章:1篇

    阅读:2311
    JMS

    文章:13篇

    阅读:13636
    Dubbo

    文章:20篇

    阅读:57632
    Nginx

    文章:21篇

    阅读:67457
    搜索优化

    文章:24篇

    阅读:28765
    Python

    文章:55篇

    阅读:45736
    Android

    文章:80篇

    阅读:255268
    算法

    文章:1篇

    阅读:648
    MongoDB

    文章:29篇

    阅读:1316
    最新评论