Python Cookbook学习笔记ch5_03

点我这里更好看

5.14 忽略文件名编码

  • 问题:想使用原始文件名执行文件的I/O操作,即文件名并不经过系统默认的编码去解码或者编码
  • 方案:使用一个原始字节串来指定文件名
# 默认情况,所有的文件名都会根据sys.getfilesystemencoding()返回的文本编码来解码或者编码
import sys
sys.getfilesystemencoding()
'utf-8'
with open('data_file/jalape\xf1o.txt','w') as f:
    f.write('Spicy!')
import os
os.listdir('data_file/.')
['.ipynb_checkpoints',
 'ch2_3_test',
 'ch4_02.txt',
 'ch5_1.txt',
 'ch5_2.txt',
 'ch5_3.txt',
 'ch5_4.bin',
 'data',
 'data.bin',
 'data2.gz',
 'jalapeño.txt',
 'somefile.txt',
 'test1.json',
 'test1_3.txt',
 'test5_09.bin',
 'test5_9.bin']

5.15 打印不合法的文件名

  • 问题:打开文件时出现UnicodeEncodeError和surrogates not allowed
  • 方案:见下
def bad_filename(filename):
    return repr(filename)[1:-1]
try:
    print(filename)
except UnicodeEncodeError:
    print(bad_filename(filename))
  • 也可以通过下面的方式解决,它重新进行了编码
def  bad_filename(filename):
    temp = filename.encode(sys.getfilesystemencoding(),errors = 'surrogateescape')
    return temp.dedcode('latin-1')

5.16增加或者改变已经打开的编码

  • 问题:如何在不关闭已经打开的文件前提下,增加或者改变它的Unicode编码
  • 方案:如果想要给一个二进制打开的文件添加Unicode编码/解码,可以使用io.TextIOWrapper()对象包装它。
import urllib.request
import io
u = urllib.request.urlopen('http://www.python.org')
f = io.TextIOWrapper(u,encoding='utf-8')
text = f.read()
text[0:50]
'<!doctype html>\n<!--[if lt IE 7]>   <html class="n'
  • 如果你想修改一个已经打开的文本模式的文件的编码方式,可以使用detach()方法移除已经存在的文本编码层,并使用新的编码方式
import sys
sys.stdout.encoding
'UTF-8'
sys.stdout = io.TextIOWrapper(sys.stdout.detach(),encoding='latin-1')
sys.stdout.encoding()
# 未成功
---------------------------------------------------------------------------

UnsupportedOperation                      Traceback (most recent call last)

<ipython-input-23-5eefd3a15c4e> in <module>()
----> 1 sys.stdout = io.TextIOWrapper(sys.stdout.detach(),encoding='latin-1')
      2 sys.stdout.encoding()
      3 # 未成功


UnsupportedOperation: detach
  • I/O 系统由一系列的层次构建而成
f = open('data_file/sample.txt','w',encoding='utf-8')
f
<_io.TextIOWrapper name='data_file/sample.txt' mode='w' encoding='utf-8'>
f.buffer
<_io.BufferedWriter name='data_file/sample.txt'>
f.buffer.raw
<_io.FileIO name='data_file/sample.txt' mode='wb' closefd=True>
  • io.TextIOWrapper 是一个编码和解码 Unicode 的文本处理层, io.BufferedWriter 是一个处理二进制数据的带缓冲的 I/O 层, io.FileIO 是一个表示操作系统底层文件描述符的原始文件。增加或改变文本编码会涉及增加或改变最上面的io.TextIOWrapper 层。

5.17 将字节写入文本文件

  • 问题:想在文本模式打开的文件中写入原始的字节数据
  • 方案:将字节数据写入缓冲区即可
  • 注意:本节内容正好和书上的相反,书上第一个失败,第二个成功
import sys
sys.stdout.write(b'hello\n')
hello
sys.stdout.buffer.write(b'hello\n')
---------------------------------------------------------------------------

AttributeError                            Traceback (most recent call last)

<ipython-input-31-7716b18a2f15> in <module>()
----> 1 sys.stdout.buffer.write(b'hello\n')


AttributeError: 'OutStream' object has no attribute 'buffer'

5.18将文件描述符包装成文件对象

  • 问题:有一个对应于操作系统上的已经打开的I/O通道的整型文件描述符,将它包装成一个更高层次的python文件对象
  • 方案:使用open()函数传入一个参数
  • 注意:一个文件描述符和一个打开的普通文件是不一样的。文件描述符仅仅是一个由操作系统指定的整数,用来指代某个系统的 I/O 通道
import os 
fd = os.open('data_file/somefile.txt',os.O_WRONLY|os.O_CREAT)
f = open(fd,'wt')
f.write('hello world \n')
f.close()
  • 当高层的文件对象被关闭或者破坏的时候,底层的文件描述符也被关闭,可以通过设置closefd=Flase.
import os 
fd = os.open('data_file/somefile.txt',os.O_WRONLY|os.O_CREAT)
f = open(fd,'wt',closefd=False)
pass

5.19 创建临时文件和文件夹

  • 问题:创建一个临时的文件或者目录,使用完后可以自动的销毁
  • 方案:使用tempfile模块
  • 提示:TemporaryFile() 的第一个参数是文件模式,通常来讲文本模式使用 w+t ,二进制模式使用 w+b 。这个模式同时支持读和写操作
from tempfile import TemporaryFile
with TemporaryFile('w+t') as f:
    f.write('hello world \n')
    f.write('testing\n')
    f.seek(0)
    data = f.read()
data
'hello world \ntesting\n'
  • TemporaryFile() 还支持同open()函数一样的参数
from tempfile import TemporaryFile
with TemporaryFile('w+t',encoding='utf-8') as f:
    pass
  • 通过TemporaryFile创建的文件是匿名的,甚至连目录都没有,可以使用NamedTemporaryFile()
  • 同样结果文件在被关闭后会自动删除,如果不想这样做,可以传入一个参数delete=False
from tempfile import NamedTemporaryFile
with NamedTemporaryFile('w+t') as f:
    print('filename is : ',f.name)
filename is :  C:\Users\AppData\Local\Temp\tmpqqexlim2
  • 为了创建一个目录,可以使用tempfile.TemporaryDirectory()
from tempfile import TemporaryDirectory
with TemporaryDirectory() as dirname:
    print('dirname is ',dirname)
dirname is  C:\Users\方立超\AppData\Local\Temp\tmpyfaribyy

5.20与串行端口的通信

  • 问题:想通过串口进行读写数据
  • 方案:选择使用pySerial包
import serial
ser = serial.Serial('1',#device name varies
                    baudrate=9600,
                    bytesize = 8,
                    parity = 'N',
                    stopbits = 1
                   )
ser.write(b'G1 X50 Y50\r\n')
ser.readline()

5.21序列化Python对象

  • 问题:需要将一个Python对象序列化为一个字节流,以便将它保存到一个文件、存储到数据库或者网络传输
  • 方案:使用pickle模块
import pickle
data = 'afasfa'
f = open('data_file/test5_21','wb')
pickle.dump(data,f)
  • 为了将一个对象转化为一个字符串,可以使用pickle.dump()
s = pickle.dumps(data)
s
b'\x80\x03X\x06\x00\x00\x00afasfaq\x00.'
  • 为了从字节流中恢复一个对象,使用pickle.load()或者pickle.loads()
f = open('data_file/test5_21','rb')
data = pickle.load(f)
data
'afasfa'
data = pickle.loads(s)
s
b'\x80\x03X\x06\x00\x00\x00afasfaq\x00.'
  • pickle 是一种 Python 特有的自描述的数据编码。通过自描述,被序列化后的数据包含每个对象开始和结束以及它的类型信息。
import pickle
f = open('data_file/somedata','wb')
pickle.dump([1,2,3,4],f)
pickle.dump('hello',f)
pickle.dump({'apple','pear','banana'},f)
f.close()
f = open('data_file/somedata','rb')
pickle.load(f)
[1, 2, 3, 4]
pickle.load(f)
'hello'
  • 此外可以序列化函数,类,接口,但是结果数据仅仅将它们的名称编码成对应的代码对象
  • 千万不要对不信任的数据使用 pickle.load().
  • 一定要保证 pickle 只在相互之间可以认证对方的解析器的内部使用
import math
import pickle
pickle.dumps(math.cos)
b'\x80\x03cmath\ncos\nq\x00.'
  • 有些类型的对象是不能被序列化的。这些通常是那些依赖外部系统状态的对象,比如打开的文件,网络连接,线程,进程,栈帧等等用户自定义类可以通过提供__getstate__() 和 __setstate__() 方法来绕过这些限制。如果定义了这两个方法,pickle.dump() 就会调用 __getstate__() 获取序列化的对象。类似的,__setstate__()在反序列化时被调用。
import time
import threading
import pickle
class Countdown:
    def __init__(self,n):
        self.n = n
        self.thr = threading.Thread(target = self.run)
        self.thr.daemon = True
        self.thr.start()

    def run(self):
        while self.n>0:
            print('T-minus',self.n)
            self.n -= 1
            time.sleep(3)

    def __getstate__(self):
        return self.n

    def __setstate__(self,n):
        self.__init__(n)
c = Countdown(10)
T-minus 10
T-minus 9
T-minus 8
f = open('data_file/cstate.p','wb')
pickle.dump(c,f)
f.close()
f = open('data_file/cstate.p','rb')
c = pickle.load(f)
c
T-minus




<__main__.Countdown at 0x596a310>



 7
T-minus 7
T-minus 6
T-minus 6
T-minus 5
T-minus 5
T-minus 4
T-minus 4
T-minus 3
T-minus 3
T-minus 2
T-minus 2
T-minus 1
T-minus 1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值