IO编程


IO编程

文件读写


在磁盘上读写文件的功能都是由操作系统提供的,现在操作系统不允许程序直接读取磁盘,所以读写文件就是请求操作系统打开一个文件对象,然后通过操作系统提供的这个接口从这个文件对象中读写文件

文件使用完毕后必须关闭,因为文件对象会占用操作系统的资源

由于文件读写时可能会产生IOError,一旦出错,f.close()就不会执行。所以我们用try,finally

try:
    f = open('file', 'r')
    print(f.read())
finally:
    if f:
        f.close()

但是每次这么写很费事,python给我们提供了with语句

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

with语句的功能和try…finally的功能是一样的,但是不用写f.close()

for line in f.readlines():
    print(line.strip())

要读取二进制文件,如图片视频等

f = open('file', 'rb')
  • 要读取非utf-8编码的文本文件,需要给open函数传入encoding参数
  • 如果遇到编码不规范的文件,可能会遇到UnicodeDecodeError,可以在open函数中传入errors参数,表示如果遇到编码错误则忽略
f.open('gbk_file', 'r', encoding='gbk', errors='ignore')

写文件也同样如此

with open('file', 'w') as f:
    f.write()

要写入特定编码的文本文件,需要给open函数传入encoding参数,将字符串自动转换成指定编码

StringIO和BytesIO


很多时候,数据读写也不一定是文件,也可以再内存中读写

StringIO就是在内存中读写数据

from io import StringIO
f = StringIO()
f.write('hello world')
11
f.getvalue()
'hello world'

如果要操作二进制数据,则要用BytesIO

from io import BytesIO
f = BytesIO()
f.write('中文'.encode('utf-8'))   #写入的是经过utf-8编码的bytes
f.getvalue()
b'\xe4\xb8\xad\xe6\x96\x87'

操作文件和目录


python 内置的os模块可以直接调用操作系统提供的接口函数

import os
print(os.name)   #操作系统类型 nt是window,posix是linux系统
nt
os.environ
environ({'PROGRAMFILES': 'C:\\Program Files', 'USERDOMAIN': 'DESKTOP-H547PQ0', 'FPS_BROWSER_USER_PROFILE_STRING': 'Default', 'PAGER': 'cat', 'USERPROFILE': 'C:\\Users\\lovelyfrog', 'CHOCOLATEYINSTALL': 'C:\\ProgramData\\chocolatey', 'HOMEDRIVE': 'C:', 'PATH': 'C:\\ProgramData\\Oracle\\Java\\javapath;C:\\Program Files\\PHP\\v7.0;C:\\Python27\\;C:\\Python27\\Scripts;C:\\Users\\lovelyfrog\\Python27\\;C:\\Users\\lovelyfrog\\Python27\\Scripts;C:\\WINDOWS\\system32;C:\\WINDOWS;C:\\WINDOWS\\System32\\Wbem;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\;C:\\Program Files\\Redis\\;C:\\ProgramData\\chocolatey\\bin;C:\\ProgramData\\chocolatey\\lib\\msys2;C:\\Program Files\\Git\\cmd;C:\\Program Files\\nodejs\\;C:\\WINDOWS\\system32\\config\\systemprofile\\AppData\\Local\\Microsoft\\WindowsApps;C:\\Users\\lovelyfrog\\AppData\\Local\\Programs\\Python\\Python35\\Scripts\\;C:\\Users\\lovelyfrog\\AppData\\Local\\Programs\\Python\\Python35\\;C:\\Users\\lovelyfrog\\AppData\\Local\\Microsoft\\WindowsApps;C:\\Users\\lovelyfrog\\Documents\\机器学习实战;C:\\Users\\lovelyfrog\\Documents\\python crawler\\phantomjs-2.1.1-windows\\bin\\;C:\\tools\\msys64;C:\\Users\\lovelyfrog\\AppData\\Roaming\\npm;D:\\biomechanics\\code;D:\\amp\\php;C:\\Users\\lovelyfrog\\AppData\\Local\\Programs\\Python\\Python35\\Scripts\\;C:\\Users\\lovelyfrog\\AppData\\Local\\Programs\\Python\\Python35\\;C:\\Users\\lovelyfrog\\AppData\\Local\\Microsoft\\WindowsApps;C:\\Users\\lovelyfrog\\Documents\\机器学习实战;C:\\Users\\lovelyfrog\\Documents\\python crawler\\phantomjs-2.1.1-windows\\bin\\;C:\\ProgramData\\chocolatey\\lib\\msys2;C:\\tools\\msys64;C:\\Users\\lovelyfrog\\AppData\\Roaming\\npm;D:\\biomechanics\\code;', 'OS': 'Windows_NT', 'PROGRAMFILES(X86)': 'C:\\Program Files (x86)', 'COMPUTERNAME': 'DESKTOP-H547PQ0', 'CHOCOLATEYTOOLSLOCATION': 'C:\\tools', 'PROCESSOR_REVISION': '3d04', 'CLICOLOR': '1', 'PSMODULEPATH': 'C:\\Program Files\\WindowsPowerShell\\Modules;C:\\WINDOWS\\system32\\WindowsPowerShell\\v1.0\\Modules', 'JPY_PARENT_PID': '1276', 'MOZ_PLUGIN_PATH': 'C:\\Program Files (x86)\\Foxit Software\\Foxit Reader\\plugins\\', 'TEMP': 'C:\\Users\\LOVELY~1\\AppData\\Local\\Temp', 'MPLBACKEND': 'module://ipykernel.pylab.backend_inline', 'USERNAME': 'lovelyfrog', 'PROGRAMW6432': 'C:\\Program Files', 'PROCESSOR_ARCHITECTURE': 'AMD64', 'PUBLIC': 'C:\\Users\\Public', 'TMP': 'C:\\Users\\LOVELY~1\\AppData\\Local\\Temp', 'ALLUSERSPROFILE': 'C:\\ProgramData', 'PROCESSOR_IDENTIFIER': 'Intel64 Family 6 Model 61 Stepping 4, GenuineIntel', 'SYSTEMROOT': 'C:\\WINDOWS', 'COMSPEC': 'C:\\WINDOWS\\system32\\cmd.exe', 'HOMEPATH': '\\Users\\lovelyfrog', 'COMMONPROGRAMFILES': 'C:\\Program Files\\Common Files', 'PROMPT': '$P$G', 'JPY_INTERRUPT_EVENT': '1272', 'WINDIR': 'C:\\WINDOWS', 'NUMBER_OF_PROCESSORS': '4', 'LOCALAPPDATA': 'C:\\Users\\lovelyfrog\\AppData\\Local', 'TERM': 'xterm-color', 'LOGONSERVER': '\\\\DESKTOP-H547PQ0', 'PATHEXT': '.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC', 'PROCESSOR_LEVEL': '6', 'ONEDRIVE': 'C:\\Users\\lovelyfrog\\OneDrive', 'COMMONPROGRAMW6432': 'C:\\Program Files\\Common Files', 'USERDOMAIN_ROAMINGPROFILE': 'DESKTOP-H547PQ0', 'GIT_PAGER': 'cat', 'SYSTEMDRIVE': 'C:', 'CHOCOLATEYLASTPATHUPDATE': '周四 7月 20 13:52:42 2017', 'APPDATA': 'C:\\Users\\lovelyfrog\\AppData\\Roaming', 'PROGRAMDATA': 'C:\\ProgramData', 'IPY_INTERRUPT_EVENT': '1272', 'SESSIONNAME': 'Console', 'FPS_BROWSER_APP_PROFILE_STRING': 'Internet Explorer', 'VS140COMNTOOLS': 'C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\Common7\\Tools\\', 'COMMONPROGRAMFILES(X86)': 'C:\\Program Files (x86)\\Common Files'})
os.environ.get('PATH')
'C:\\ProgramData\\Oracle\\Java\\javapath;C:\\Program Files\\PHP\\v7.0;C:\\Python27\\;C:\\Python27\\Scripts;C:\\Users\\lovelyfrog\\Python27\\;C:\\Users\\lovelyfrog\\Python27\\Scripts;C:\\WINDOWS\\system32;C:\\WINDOWS;C:\\WINDOWS\\System32\\Wbem;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\;C:\\Program Files\\Redis\\;C:\\ProgramData\\chocolatey\\bin;C:\\ProgramData\\chocolatey\\lib\\msys2;C:\\Program Files\\Git\\cmd;C:\\Program Files\\nodejs\\;C:\\WINDOWS\\system32\\config\\systemprofile\\AppData\\Local\\Microsoft\\WindowsApps;C:\\Users\\lovelyfrog\\AppData\\Local\\Programs\\Python\\Python35\\Scripts\\;C:\\Users\\lovelyfrog\\AppData\\Local\\Programs\\Python\\Python35\\;C:\\Users\\lovelyfrog\\AppData\\Local\\Microsoft\\WindowsApps;C:\\Users\\lovelyfrog\\Documents\\机器学习实战;C:\\Users\\lovelyfrog\\Documents\\python crawler\\phantomjs-2.1.1-windows\\bin\\;C:\\tools\\msys64;C:\\Users\\lovelyfrog\\AppData\\Roaming\\npm;D:\\biomechanics\\code;D:\\amp\\php;C:\\Users\\lovelyfrog\\AppData\\Local\\Programs\\Python\\Python35\\Scripts\\;C:\\Users\\lovelyfrog\\AppData\\Local\\Programs\\Python\\Python35\\;C:\\Users\\lovelyfrog\\AppData\\Local\\Microsoft\\WindowsApps;C:\\Users\\lovelyfrog\\Documents\\机器学习实战;C:\\Users\\lovelyfrog\\Documents\\python crawler\\phantomjs-2.1.1-windows\\bin\\;C:\\ProgramData\\chocolatey\\lib\\msys2;C:\\tools\\msys64;C:\\Users\\lovelyfrog\\AppData\\Roaming\\npm;D:\\biomechanics\\code;'

操作文件和目录

#查看当前目录
os.path.abspath('.')
'D:\\python_project\\some_thought'

把两个路径合成一个时,不要直接拼接字符串,而要用os.path.join(),这样可以正确处理不同操作系统的分隔符,同理拆分路径时要用os.path.split()

os.path.join('D:\python','sss')
'D:\\python\\sss'
os.path.split('D:\python_project\cat.jpg')
('D:\\python_project', 'cat.jpg')
os.path.splitext('D:\python_project\cat.jpg')   #有时会非常方便
('D:\\python_project\\cat', '.jpg')
#文件操作
os.rename('test.txt','test.py')
os.remove('test.py')

但是复制文件的函数在os中是不存在的,幸运的是shutil模块提供了copyfile()函数,shutil模块可以看作是os的补充

利用python的一些特性来过滤文件

[x for x in os.listdir('.') if os.path.isdir(x)]  #获取当前目录下所有文件夹
['.idea', '.ipynb_checkpoints', 'ItChat-master']
[x for x in os.listdir('.') if os.path.isfile(x) and os.path.splitext(x)[1]=='.py']
['custom_made_class.py']

序列化


我们把变量从内存中编程可存储或者可传输的过程就叫做序列化,在python中叫pickling.序列化后就可以将序列化后的内容写入磁盘或者传输到网上

import pickle
d = dict(name='lovelyfrog', age=20, score=90)
pickle.dumps(d)
b'\x80\x03}q\x00(X\x05\x00\x00\x00scoreq\x01KZX\x04\x00\x00\x00nameq\x02X\n\x00\x00\x00lovelyfrogq\x03X\x03\x00\x00\x00ageq\x04K\x14u.'
f = open('dump.txt','wb')
pickle.dump(d, f)
f.close()
f = open('dump.txt', 'rb')
d = pickle.load(f)
d
{'age': 20, 'name': 'lovelyfrog', 'score': 90}

pickle只适用于python

JSON


如果在不同编程语言中传递对象,就必须把对象序列化为标准格式,最好的方法是序列成JSON,JSON表示的对象就是标准的JavaScript语言的对象

python内置的json模块提供了非常完善的从python对象到JSON格式的转换,类似的dump()可以将JSON写入一个file-like-object中
从JSON反序列化,可以用loads(),或者load()从一个file-like object中读取字符串并反序列化

import json
d = dict(name='lovelyfrog', age=20, score=90)
json.dumps(d)
'{"score": 90, "name": "lovelyfrog", "age": 20}'
json_str = json.dumps(d)
json.loads(json_str)
{'age': 20, 'name': 'lovelyfrog', 'score': 90}
json_str['name']
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-37-c351198a8340> in <module>()
----> 1 json_str['name']


TypeError: string indices must be integers

类对象不是一个可以json序列化的对象,但是我们可以更改default参数,为类写一个转换函数

class Student(object):
    def __init__(self,name,age,score):
        self.name=name
        self.age=age
        self.score=score

s = Student('lovelyfrog',20,90)
json.dumps(s)
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-33-2531144bea7e> in <module>()
----> 1 json.dumps(s)


~\AppData\Local\Programs\Python\Python35\lib\json\__init__.py in dumps(obj, skipkeys, ensure_ascii, check_circular, allow_nan, cls, indent, separators, default, sort_keys, **kw)
    228         cls is None and indent is None and separators is None and
    229         default is None and not sort_keys and not kw):
--> 230         return _default_encoder.encode(obj)
    231     if cls is None:
    232         cls = JSONEncoder


~\AppData\Local\Programs\Python\Python35\lib\json\encoder.py in encode(self, o)
    196         # exceptions aren't as detailed.  The list call should be roughly
    197         # equivalent to the PySequence_Fast that ''.join() would do.
--> 198         chunks = self.iterencode(o, _one_shot=True)
    199         if not isinstance(chunks, (list, tuple)):
    200             chunks = list(chunks)


~\AppData\Local\Programs\Python\Python35\lib\json\encoder.py in iterencode(self, o, _one_shot)
    254                 self.key_separator, self.item_separator, self.sort_keys,
    255                 self.skipkeys, _one_shot)
--> 256         return _iterencode(o, 0)
    257 
    258 def _make_iterencode(markers, _default, _encoder, _indent, _floatstr,


~\AppData\Local\Programs\Python\Python35\lib\json\encoder.py in default(self, o)
    177 
    178         """
--> 179         raise TypeError(repr(o) + " is not JSON serializable")
    180 
    181     def encode(self, o):


TypeError: <__main__.Student object at 0x000001BE15084518> is not JSON serializable

同样的道理,如果我们要把JSON反序列化为一个Student对象实例,loads()方法首先转换出一个dict对象,然后,我们传入的object_hook函数负责把dict转换为Student实例

def student2dict(std):
    return {
    'name':std.name,
    'age':std.age,
    'score':std.score
    }
print(json.dumps(s, default=student2dict))
{"score": 90, "name": "lovelyfrog", "age": 20}

通常class都有一个dict属性用来储存实例变量,

print(json.dumps(s.__dict__))
{"score": 90, "age": 20, "name": "lovelyfrog"}
def dict2student(d):
    return Student(d['name'], d['age'], d['score'])

print(json.loads(json_str, object_hook=dict2student))
<__main__.Student object at 0x000001BE1510A198>

文章作者: lovelyfrog
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 lovelyfrog !
 上一篇
异步IO 异步IO
异步IO 协程def odd(): n=1 while True: yield n n+=2 odd_num = odd() count = 0 for o in odd_num:
2017-09-18
下一篇 
itchat入门 itchat入门
itchat入门 import itchat itchat.auto_login() Getting uuid of QR code. Downloading QR code. Please scan the QR code to lo
2017-09-08
  目录