专栏首页一Li小麦hand first python 选读(1)

hand first python 选读(1)

文件读取与异常

文件读取与判断

os模块是调用来处理文件的。

先从最原始的读取txt文件开始吧!

新建一个aaa.txt文档,键入如下英文名篇:

Li Lei:"Hello,Han Meimei."
Han Meimei:"Hi,Li Lei.How are you?"
Li Lei:"I am fine,thank you.And you?"

同目录下创建一个新的file.py文档

import os
os.getcwd()

data=open('aaa.txt')
# 打开文件
print(data.readline(),end='')
# 读取文件
print(data.readline(), end='')

data.seek(0)
# 又回到最初的起点

for line in data:
    print(line,end='')

结果如下

如果文件不存在怎么办?

import os

if os.path.exists('aaa.txt'):
    # 业务代码
else:
    print('error:the file is not existed.')

split切分

现在我们要把这个桥段转化为第三人称的形式

for line in data:
    (role,spoken)=line.split(':')
    print(role,end='')
    print(' said:',end='')
    print(spoken,end='')

这里是个极其简单对话区分。如果我把对话稍微复杂点

。。。

Han Meimei:"There is a question:shall we go to the bed together?"
(pause)
Li Lei:"Oh,let us go to the bed together!"

关键时刻岂可报错。

首先发现问题出在冒号,split方法允许第二个参数.

以下实例展示了split()函数的使用方法:

#!/usr/bin/python

str = "Line1-abcdef \nLine2-abc \nLine4-abcd";
print str.split( );
print str.split(' ', 1 );

以上实例输出结果如下:

['Line1-abcdef', 'Line2-abc', 'Line4-abcd']
['Line1-abcdef', '\nLine2-abc \nLine4-abcd']
data = open('aaa.txt')
# 打开文件

for line in data:
    (role,spoken)=line.split(':',1)
    print(role,end='')
    print(' said:',end='')
    print(spoken,end='')

取反:not

结果pause解析不了。每一行做多一个判断。取反用的是 not方法,查找用的是 find方法。

Python find() 方法检测字符串中是否包含子字符串 str ,如果指定 beg(开始) 和 end(结束) 范围,则检查是否包含在指定范围内,如果包含子字符串返回开始的索引值,否则返回-1。

find()方法语法:

str.find(str, beg=0, end=len(string))

考虑这样写

for line in data:
    if not line.find(':')==-1:
        (role,spoken)=line.split(':',1)
        print(role,end='')
        print(' said:',end='')
        print(spoken,end='')
data.close()

关注代码本身的目的功能:try...except...捕获处理异常

剧本里的对话千差万别,而我只想要人物的对话。不断增加代码复杂度是绝对不明智的。

python遇到代码错误会以 traceback方式告诉你大概出了什么错,并中断处理流程(程序崩了!)。

try...except...类似try...catch语法,允许代码中的错误发生,不中断业务流程。

在上述业务代码中我想统一忽略掉所有木有冒号的文本行

可以 这么写:

for line in data:
    try:
        (role,spoken)=line.split(':',1)
        print(role,end='')
        print(' said:',end='')
        print(spoken,end='')
    except:
        pass

pass是python中的null语句,理解为啥也不做。

通过这个语法,忽略处理掉了所有不必要的复杂逻辑。

复杂系统中,aaa.txt可能是不存在的,你固然可以用 if读取,还有一个更激进(先进)的写法:

import os

try:
    data = open('aaa.txt')
    # 打开文件

    for line in data:
        try:
            (role,spoken)=line.split(':',1)
            print(role,end='')
            print(' said:',end='')
            print(spoken,end='')
        except:
            pass
except:
    print('error:could not read the file.')

两种逻辑是不一样的,上述是无法读取(可能读取出错),if是路径不存在。于是引发了最后一个问题。

错误类型指定

过于一般化的代码,总是不能很好地判断就是是哪出了错。try语句无法判断:究竟是文件路径不对还是别的问题

import os

try:
    data = open('aaa.txt')
    # 打开文件

    for line in data:
        try:
            (role,spoken)=line.split(':',1)
            print(role,end='')
            print(' said:',end='')
            print(spoken,end='')
        except ValueError:
            # 参数出错
            pass
except IOError:
    # 输入输出出错
    print('error:could not find the file.')

python中异常对象有很多,可自行查阅。

数据不符合期望格式:ValueError

IOError:路径出错

数据储存到文件

业务代码工作流程可以储存到文件中保存下来。下面先看一个需求:

  1. 分别创建一个名为lilei和hanmeimei的空列表
  2. 删除一个line里面的换行符(replace方法和js中几乎一样。去除左右空格用 strip方法)
  3. 给出条件和代码,根据role的值将line添加到适当的列表中
  4. 输出各自列表。

简单说就是一个条件查询的实现。

try:
    data = open('aaa.txt')
    lilei = []
    hanmeimei = []
    for line in data:
        try:
            (role, spoken) = line.split(':', 1)
            spoken = spoken.replace('\n', '')
            if role == 'Li Lei':
                lilei.append(spoken)
            else:
                hanmeimei.append(spoken)
        except ValueError:
            pass
    data.close()
except IOError:
    print('error:the file is not found.')

print(lilei)
print(hanmeimei)

很简单。

写模式:open('bbb.txt',w')

open方法默认为读模式 open('bbb.txt','r'),写模式对因为 open('bbb.txt','w')

在同目录下创建一个 bbb.txt

写入文件可以用以下命令:

out = open('bbb.txt', 'w')
print('we are who we are.', file=out)
out.close()

文件访问模式

释义

r

读取,是为默认模式

w

打开一个文件,覆写文件内容,如没有则创建。

w+

读取和追加写入(不清除)

a

追加写入

打开的文件必须运行关闭!

好了,介绍完知识之后可以在上一节代码中分别写入文件吧

try:
    data = open('aaa.txt')
    lilei = []
    hanmeimei = []
    for line in data:
        try:
            (role, spoken) = line.split(':', 1)
            spoken = spoken.strip()
            if role == 'Li Lei':
                lilei.append(spoken)
            else:
                hanmeimei.append(spoken)
        except ValueError:
            pass
    data.close()

    try:
        _lilei = open('lilei.txt', 'w')
        _hanmeimei = open('hanmeimei.txt', 'w')

        print(lilei,file=_lilei)
        print(hanmeimei,file=_hanmeimei)

        _lilei.close()
        _hanmeimei.close()
        print('works completed.')
    except IOError:
        print('file error.')

except IOError:
    print('error:the file is not found.')

测试成功,但以上代码有个问题:我需要无论IOError都运行一套代码。并且在文件创建后关闭

扩展try语句

当我尝试以 read模式打开一个文件,:

try:
        data = open('lilei.txt')
    except IOError as err:
        print('file error.'+str(err))
    finally:
        if 'data' in locals():
            _lilei.close()
        print('works completed.')
  • finally:无论是否运行成功都执行的代码。
  • locals():告诉你文件是否成功被创建并打开。
  • as xxx:为异常对象命名,并且通过str()转化为字符以便打印,也是一个赋值过程

实在太麻烦了。

with语句

with语句利用了一个上下文管理协议。有了它就不用些 finally了。

目前为止条件查找的方案是这样的

# ...

    try:
        _lilei = open('lilei.txt','w')
        _hanmeimei = open('hanmeimei.txt','w')

        print(lilei, file=_lilei)
        print(hanmeimei, file=_hanmeimei)
    except IOError as err:
        print('file error.'+str(err))
    finally:
        if '_lilei' in locals():
            _lilei.close()
        if '_hanmeimei' in locals():
            _hanmeimei.close()
        print('works completed.')

except IOError:
    print('error:the file is not found.')

用with重写之后:

try:
        with open('lilei.txt','w') as _lilei:
            print(lilei, file=_lilei)
        with open('hanmeimei.txt','w') as _hanmeimei:        
            print(hanmeimei, file=_hanmeimei)
        print('works completed.')
    except IOError as err:
        print('file error.'+str(err))

写好之后就非常简洁了。

因地制宜选择输出样式

对于列表数据来说,直接存字符串是很不合适的。现在我要把第二章中的flatten加进来并加以改造。

# base.py

def flatten(_list, count=False, level=0):
    if(isinstance(_list, list)):
        for _item in _list:
            flatten(_item,count,level+1)
    else:
        if count:
            for step in range(level):
                print("\t", end='')
            print(_list)
        else:
            print(_list)

需求:向flatten添加第四个参数,标识数据写入的位置,并允许缺省。

# base.py
def flatten(_list, count=False, level=0,_file=False):
    if(isinstance(_list, list)):
        for _item in _list:
            flatten(_item,count,level+1,_file)
    else:

        if count:
            for step in range(level):
                print("\t", end='',file=_file)
            print(_list,file=_file)
        else:
            print(_list)

调用

import base as utils
try:
    data = open('aaa.txt')
    lilei = []
    hanmeimei = []
    for line in data:
        try:
            (role, spoken) = line.split(':', 1)
            spoken = spoken.strip()
            if role == 'Li Lei':
                lilei.append(spoken)
            else:
                hanmeimei.append(spoken)
        except ValueError:
            pass
    data.close()

    try:
        with open('lilei.txt','w') as _lilei:
            utils.flatten(lilei,True,0,_lilei)
        with open('hanmeimei.txt','w') as _hanmeimei:        
            utils.flatten(hanmeimei, True, 0, _hanmeimei)
        print('works completed.')
    except IOError as err:
        print('file error.'+str(err))


except IOError:
    print('error:the file is not found.')

输出成功

把格局拉高点吧,这仍然是一个高度定制化的代码。

pickle库的使用

pickle库介绍

pickle是python语言的一个标准模块,安装python后已包含pickle库,不需要单独再安装。

pickle模块实现了基本的数据序列化和反序列化。通过pickle模块的序列化操作我们能够将程序中运行的对象信息保存到文件中去,永久存储;通过pickle模块的反序列化操作,我们能够从文件中创建上一次程序保存的对象。

一、内存中操作:

import pickle
#dumps 转化为二进制文件
li = [11,22,33]
r = pickle.dumps(li)
print(r)

#loads 将二进制数据编译出来
result = pickle.loads(r)
print(result)

二、文件中操作:

#dump:以二进制形式打开(读取:rb,写入wb)文件
li = [11,22,33]
pickle.dump(li,open('db','wb'))

#load
ret = pickle.load(open('db','rb'))
print(ret)

把二进制文件写入文件中:

try:
        with open('lilei.txt','wb') as _lilei:
            # utils.flatten(lilei,True,0,_lilei)
            pickle.dump(lilei,_lilei)
        with open('hanmeimei.txt','wb') as _hanmeimei:        
            # utils.flatten(hanmeimei, True, 0, _hanmeimei)
            pickle.dump(hanmeimei,_hanmeimei)
        print('works completed.')
    except IOError as err:
        print('file error.'+str(err))

    except pickle.PickleError as pError:
        print('err:'+str(pError))

数据已经被写入。

举例说:如何打开lileii.txt并正确编译呢?

new_lilei=[]
try:
    with open('lilei.txt','rb') as _new_lilei:
        new_lilei = pickle.load(_new_lilei)
        print(utils.flatten(new_lilei))
except IOError as io:
    print('err:'+str(io))
except pickle.PickleError as pError:
    print('pickleError'+str(pError))

测试成功。

用pickle的通用io才是上策,

本文分享自微信公众号 - 一Li小麦(gh_c88159ec1309),作者:一li小麦

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-12-16

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • head first python选读(4):web 开发

    这个app.py是所有文件的入口。因此所有的文件都依靠这个文件进行交互。路径以根目录为主。

    一粒小麦
  • 《javascript数据结构和算法》读书笔记(5):集合

    在创建时有一个细节,使用对象(items)而不是数组来创建集合。但使用数组的话意义似乎不大。

    一粒小麦
  • webview

    webview是对rn开发的一个重要补充,由于性能原因,旧版自带的webview即将被移除。

    一粒小麦
  • 告诉你 38 个 MySQL 数据库的小技巧!

    培养兴趣 兴趣是最好的老师,不论学习什么知识,兴趣都可以极大地提高学习效率。当然学习 MySQL 5.6 也不例外。

    CSDN技术头条
  • MySQL数据库实用技巧

    培养兴趣   兴趣是最好的老师,不论学习什么知识,兴趣都可以极大地提高学习效率。当然学习MySQL 5.6也不例外。 夯实基础   计算机领域的技术非常强调基础...

    Kevin_Zhang
  • 告诉你38个MySQL数据库的小技巧!

    培养兴趣 兴趣是最好的老师,不论学习什么知识,兴趣都可以极大地提高学习效率。当然学习MySQL 5.6也不例外。 夯实基础 计算机领域的技术非常强调基础,刚开始...

    Java后端技术
  • 训练网络像是买彩票?神经网络剪枝最新进展之彩票假设解读

    深度神经网络已经在计算机视觉领域取得了巨大的成功,如 AlexNet、VGG 等。这些模型动辄就有上亿的参数,传统的 CPU 对如此庞大的网络一筹莫展,只有具有...

    机器之心
  • django中url路由配置及渲染方式

      今天我们学习如何配置url、如何传参、如何命名、以及渲染的方式,内容大致有以下几个方面。

    py3study
  • 前端基础-MVVM设计思想

    cwl_java
  • 盘点 Oracle 11g 中新特性带来的10大性能影响

    Oracle的任何一个新版本,总是会带来大量引人瞩目的新特性,但是往往在这些新特性引入之初,首先引起的是一些麻烦,因为对于新技术的不了解、因为对于旧环境的不适应...

    数据和云

扫码关注云+社区

领取腾讯云代金券