python中的IO编程

来源:互联网 发布:材料入库单软件 编辑:程序博客网 时间:2024/04/30 20:28

IO编程中,Stream(流)是一个很重要的概念,可以把流想象成一个水管,数据就是水管里的水,但是只能单向流动。Input Stream就是数据从外面(磁盘、网络)流进内存,Output Stream就是数据从内存流到外面去。

然后就有了同步IO和异步IO
第一种是CPU等着,也就是程序暂停执行后续代码,等100M的数据在10秒后写入磁盘,再接着往下执行,这种模式称为同步IO;
另一种方法是CPU不等待,只是告诉磁盘,“您老慢慢写,不着急,我接着干别的事去了”,于是,后续代码可以立刻接着执行,这种模式称为异步IO。

很明显,使用异步IO来编写程序性能会远远高于同步IO,但是异步IO的缺点是编程模型复杂。(此处举个例子你想去买汉堡,做汉堡需要5分钟,然后 这五分钟你去逛商场)想想看,你得知道什么时候通知你“汉堡做好了”,而通知你的方法也各不相同。如果是服务员跑过来找到你,这是回调模式,如果服务员发短信通知你,你就得不停地检查手机,这是轮询模式。总之,异步IO的复杂度远远高于同步IO。

操作IO的能力都是由操作系统提供的,每一种编程语言都会把操作系统提供的低级C接口封装起来方便使用,Python也不例外。我们后面会详细讨论Python的IO编程接口。
一.文件读写:
读写文件因为涉及到磁盘,我们不能直接对磁盘进行操作,所以进而涉及到操作系统的调用。
和C一样,其用到open指令,python这强大的语言同时也映引入了with语句帮助我们自动调用close()方法。

with open('/path/to/file', 'r') as f:    print(f.read())

调用read()会一次性读取文件的全部内容,如果文件有10G,内存就爆了,所以,要保险起见,可以反复调用read(size)方法,每次最多读取size个字节的内容。另外,调用readline()可以每次读取一行内容,调用readlines()一次读取所有内容并按行返回list。因此,要根据需要决定怎么调用。
然后这是一个叫什么file-like-Object的东西,至于具体怎么回事表示没有看懂,

可以反复调用write()来写入文件,但是务必要调用f.close()来关闭文件。当我们写文件时,操作系统往往不会立刻把数据写入磁盘,而是放到内存缓存起来,空闲的时候再慢慢写入。只有调用close()方法时,操作系统才保证把没有写入的数据全部写入磁盘。忘记调用close()的后果是数据可能只写了一部分到磁盘,剩下的丢失了。所以也有一个with的方法。然后相应的二进制文件等等之类的具体用的时候再去查,这里就不一一写了。
二.stringIO和ByteIO
StringIO和BytesIO是在内存中操作str和bytes的方法,使得和读写文件具有一致的接口。
StringIO
数据读写不一定是文件也可以在内存之中读写。

>>> f=StringIO()>>> f.write('Hello')5>>> print(f.getvalue())Hello>>> 

StringIO顾名思义就是在内存中读写str。
要把str写入StringIO,我们需要先创建一个StringIO,然后,像文件一样写入即可,getvalue()方法用于获得写入后的str。
ByteIO的读写和这个差不多。StringIO操作的只能是str,如果要操作二进制数据,就需要使用BytesIO。

>>> from io import StringIO>>> f = StringIO('Hello!\nHi!\nGoodbye!')>>> while True:...     s = f.readline()...     if s == '':...         break...     print(s.strip())...Hello!Hi!Goodbye!

三.操作文件和目录
操作系统提供的命令只是简单地调用了操作系统提供的接口函数,Python内置的os模块也可以直接调用操作系统提供的接口函数。

>>> import os>>> os.name'nt'

如果是posix,说明系统是Linux、Unix或Mac OS X,如果是nt,就是Windows系统。
获取环境变量:

>>> os.environenviron({'COMPUTERNAME': 'FEISHAOYE', 'FPS_BROWSER_USER_PROFILE_STRING': 'Default', 'USERNAME': '0', 'OS': 'Windows_NT', 'INSTALLDIR_Z-2007.03': 

操作文件和目录:

# 查看当前目录的绝对路径:>>> os.path.abspath('.')'/Users/michael'# 在某个目录下创建一个新目录,首先把新目录的完整路径表示出来:>>> os.path.join('/Users/michael', 'testdir')'/Users/michael/testdir'# 然后创建一个目录:>>> os.mkdir('/Users/michael/testdir')# 删掉一个目录:>>> os.rmdir('/Users/michael/testdir')

复制文件的函数居然在os模块中不存在!原因是复制文件并非由操作系统提供的系统调用。
幸运的是shutil模块提供了copyfile()的函数,你还可以在shutil模块中找到很多实用函数,它们可以看做是os模块的补充。
如何利用Python的特性来过滤文件。比如我们要列出当前目录下的所有目录,只需要一行代码:

>>> [x for x in os.listdir('.') if os.path.isdir(x)]['.lein', '.local', '.m2', '.npm', '.ssh', '.Trash', '.vim', 'Applications', 'Desktop', ...]

列出所有的.py文件

>>> [x for x in os.listdir('.') if os.path.isfile(x) and os.path.splitext(x)[1]=='.py']['apis.py', 'config.py', 'models.py', 'pymonitor.py', 'test_db.py', 'urls.py', 'wsgiapp.py']

四.序列化
序列化的意思就是说,程序只是在内存中运行,所以我们把变量从内存中变为可存储或可传输的过程称为序列化。Python中叫pickling。
序列化之后,就可以把序列化后的内容写入磁盘,或者通过网络传输到别的机器上。
反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling。
Python提供了pickle模块来实现序列化。首先,我们尝试把一个对象序列化并写入文件:

>>> import pickle>>> d = dict(name='Bob', age=20, score=88)>>> pickle.dumps(d)b'\x80\x03}q\x00(X\x03\x00\x00\x00ageq\x01K\x14X\x05\x00\x00\x00scoreq\x02KXX\x04\x00\x00\x00nameq\x03X\x03\x00\x00\x00Bobq\x04u.'

pickle.dumps()方法把任意对象序列化成一个bytes,然后,就可以把这个bytes写入文件。或者用另一个方法pickle.dump()直接把对象序列化后写入一个file-like Object:

>>> f = open('dump.txt', 'wb')>>> pickle.dump(d, f)>>> f.close()>>> f = open('dump.txt', 'rb')>>> d = pickle.load(f)>>> f.close()>>> d{'age': 20, 'score': 88, 'name': 'Bob'}

看看写入的dump.txt文件,一堆乱七八糟的内容,这些都是Python保存的对象内部信息。
当我们要把对象从磁盘读到内存时,可以先把内容读到一个bytes,然后用pickle.loads()方法反序列化出对象,也可以直接用pickle.load()方法从一个file-like Object中直接反序列化出对象。我们打开另一个Python命令行来反序列化刚才保存的对象。
变量的内容又回来了!
当然,这个变量和原来的变量是完全不相干的对象,它们只是内容相同而已。
Pickle的问题和所有其他编程语言特有的序列化问题一样,就是它只能用于Python,并且可能不同版本的Python彼此都不兼容,因此,只能用Pickle保存那些不重要的数据,不能成功地反序列化也没关系。
JSON
如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML,但更好的方法是序列化为JSON,
然后还有Python内置的json模块提供了非常完善的Python对象到JSON格式的转换等等之类的以后再说吧
关于python的一些基础只是我就填鸭式的先学到这里,然后转战python在大数据中的应用,开始我的python在机器学习中的应用。廖雪峰网站后面还讲到了很多东西~后面还有做了一个项目~西西~以后有时间把剩下的做完。

0 0
原创粉丝点击