从 Python到Tensorflow 学习之路(四)

从 Python到Tensorflow 学习之路(五)


最近毕业设计题目是研究对抗样本,要用tensorflow来搭建神经网络,因此python必不可少,这个不是一个传统的Python学习教程只是把学习Python过程中遇到的问题和经验记录下来(基于Python3.5),如果想要一步一步学习Python建议看下面的网站。
Python学习教程


错误、调试和测试

错误处理

  • try...except...finally...其中finally可有可无,有的话一定会被执行
  • 如果没有错误发生可以在except语句块后面加一个else,当没有错误发生时,会自动执行else语句
  • Python中所有的错误类型都继承于BaseException,所以在使用except时需要注意,它不但捕获该类型的错误,还把其子类也“一网打尽”
  • 出错的时候,一定要分析错误的调用栈信息,才能定位错误的位置。
  • 可以通过配置使用logging把错误记录在日志文件中
import logging


def foo(s):
    return 10 / int(s)


def bar(s):
    return foo(s) * 2


def main():
    try:
        bar('0')
    except Exception as e:
        logging.exception(e)


main()
print('END')

调试

  • 使用断言assert的意思是表达式n!=0应该是True,否则根据程序运行逻辑,后面的代码肯定会出错。如果断言失败,assert语句本身就会抛出AssertionError
def foo(s):
    n = int(s)
    assert n != 0, 'n is zero!'
    return 10 / n


def main():
    foo('0')


main()
  • 利用logging不会抛出错误,而且可以输出到文件。它允许你指定记录信息的级别,有debug,info,warning,error等几个级别,当我们指定level=INFO时,logging.debug就不起作用了。同理,指定level=WARNING后,debug和info就不起作用了。这样一来,你可以放心地输出不同级别的信息,也不用删除,最后统一控制输出哪个级别的信息。
import logging

logging.basicConfig(level=logging.INFO)
s = '0'
n = int(s)
logging.info('n = %d' % n)
print(10 / n)
"""
INFO:root:n = 0
Traceback (most recent call last):
  File "/home/lwp/PycharmProjects/blog_test/blog_test.py", line 10, in <module>
    print(10 / n)
ZeroDivisionError: division by zero
"""

IO编程

文件读写

  • 使用open()函数以读文件的模式打开一个文件对象,传入文件名和标识符,如果文件不存在就会抛出错误
f = open('test.txt', 'r')
"""
Traceback (most recent call last):
  File "/home/lwp/PycharmProjects/blog_test/blog_test.py", line 4, in <module>
    f = open('test.txt', 'r')
FileNotFoundError: [Errno 2] No such file or directory: 'test.txt'

"""
  • 调用read()方法可以一次性读取文件的全部内容,Python把内容读到内存,用一个str对象表示
  • 调用close()方法可以关闭文件。。文件使用完毕后必须关闭,因为文件对象会占用操作系统的资源,并且操作系统同一时间能打开的文件数量也是有限的。使用with语句来自动调用close()方法
with open('test.txt', 'r') as f:
    print(f.read())

# output:111 111
         222 222
  • 调用read()会会一次性读取文件的全部内容,如果文件有10G,内存就爆了,所以,要保险起见,可以反复调用read(size)方法,每次最多读取size个字节的内容。另外,调用readline()可以每次读取一行内容,调用readlines()一次读取所有内容并按行返回list。由于print()函数自身会换行,所以我们需要把end参数进行修改。
with open('test.txt', 'r') as f:
    l1 = f.readline()
    l2 = f.readline()
    print(l1, end='')
    print(l2)
"""
111 111
222 222
"""
with open('test.txt', 'r') as f:
    for line in f.readlines():
        print(line.strip())
  • file-like Object:像open()函数返回的这种有个read()方法的对象,在Python中统称为file-like Object。除了file外,还可以是内存的字节流,网络流,自定义流等等。file-like Object不要求从特定类继承,只要写个read()方法就行。StringIO就是在内存中创建的file-like Object,常用作临时缓冲。
  • 读取二进制文件如图片、视频等等,用'rb'模式打开文件即可
  • 要读取非UTF-8编码的文本文件,需要给open()函数传入encoding参数。遇到有些编码不规范的文件,你可能会遇到UnicodeDecodeError,因为在文本文件中可能夹杂了一些非法编码的字符。遇到这种情况,open()函数还接收一个errors参数,表示如果遇到编码错误后如何处理。最简单的方式是直接忽略。
  • 写文件时和读文件是一样的,唯一区别是调用open()函数时,传入标识符'w'或者'wb'表示写文本文件或写二进制文件。以'w'模式写入文件时,如果文件已存在,会直接覆盖(相当于删掉后新写入一个文件)。如果我们希望追加到文件末尾怎么办?可以传入'a'以追加(append)模式写入。
with open('test2.txt', 'w') as f:
    f.write('Hello world!')

StringIO和BytesIO

  • 数据读写不一定是文件,也可以在内存中读写。要把str写入StringIO,我们需要先创建一个StringIO,然后,像文件一样写入即可。getvalue()方法用于获得写入后的str
from io import StringIO
f = StringIO()
print(f.write('hello'))
# output: 5
print(f.write(' '))
# output: 1
print(f.write('world!'))
# output: 6
print(f.getvalue())
# output: hello world!
  • 要读取StringIO,可以用一个str初始化StringIO,然后像文件一样读取
from io import StringIO
f = StringIO('Hello!\nHi!\nGoodbye!')
while True:
    s = f.readline()
    if s == '':
        break;
    print(s.strip())
"""
Hello!
Hi!
Goodbye!
"""

*StringIO操作的只能是str,如果要操作二进制数据,就需要使用BytesIO。BytesIO实现了在内存中读写bytes,我们创建一个BytesIO,然后写入一些bytes

from io import BytesIO
f = BytesIO()
print(f.write('你好'.encode('utf-8')))
# output: 6
print(f.getvalue())
# output:b'\xe4\xbd\xa0\xe5\xa5\xbd'
  • 和StringIO类似,可以用一个bytes初始化BytesIO,然后,像读文件一样读取
from io import BytesIO
f = BytesIO(b'\xe4\xbd\xa0\xe5\xa5\xbd')
print(f.read())
# output:b'\xe4\xbd\xa0\xe5\xa5\xbd'

操作文件和目录

  • 环境变量:在操作系统中定义的环境变量,全部保存在os.environ这个变量中,可以直接查看。要获取某个环境变量的值,可以调用os.environ.get('key')
import os
print(os.environ)
print(os.environ.get('PATH'))
  • 查看、创建和删除目录。把两个路径合成一个时,不要直接拼字符串,而要通过os.path.join()函数。同样的道理,要拆分路径时,也不要直接去拆字符串,而要通过os.path.split()函数,这样可以把一个路径拆分为两部分,后一部分总是最后级别的目录或文件名:
import os
# 查看当前目录的绝对路径
print(os.path.abspath('.'))
# 在某个目录下创建一个新目录,首先把新目录的完整路径表示出来:
s = os.path.join(os.path.abspath('.'), 'testdir')
#os.mkdir(s)
# 删除创建的文件夹
#os.rmdir(s)
print(os.path.split(s))
# output:('/home/lwp/PycharmProjects/blog_test', 'testdir')
print(os.path.splitext(os.path.abspath('./test.txt')))
# output:('/home/lwp/PycharmProjects/blog_test/test', '.txt')


# 对文件进行重命名
os.rename('test2.txt', 'test2.py')
# 删掉文件
os.remove('test2.py')
  • 复制文件的函数在os模块中不存在,原因是复制文件并非由操作系统提供的系统调用。shutil模块提供了copyfile()的函数,可以在shutil模块中找到很多实用函数,它们可以看做是os模块的补充
  • 可以利用Python的特性来过滤文件。比如我们要列出当前目录下的所有目录
import os
# 列出当前目录下的所有目录
print([x for x in os.listdir('.') if os.path.isdir(x)])
# 列出所有的.py文件
print([x for x in os.listdir('.') if os.path.isfile(x) and os.path.splitext(x)[1] == '.py'])

序列化

  • 变量从内存中变成可存储或传输的过程称之为序列化。序列化之后,就可以把序列化后的内容写入磁盘,或者通过网络传输到别的机器上。反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling。首先我们尝试将一个对象序列化并写入文件。pickle.dump()直接把对象序列化后写入一个file-like Object。
import pickle
d = dict(name='Bob', age=10, score=88)
print(pickle.dumps(d))
# output:b'\x80\x03}q\x00(X\x03\x00\x00\x00ageq\x01K\nX\x05\x00\x00\x00scoreq\x02KXX\x04\x00\x00\x00nameq\x03X\x03\x00\x00\x00Bobq\x04u.'
with open('testfile.txt', 'wb') as f:
    pickle.dump(d, f)
  • 当我们要把对象从磁盘读到内存时,可以先把内容读到一个bytes,然后用pickle.loads()方法反序列化出对象,也可以直接用pickle.load()方法从一个file-like Object中直接反序列化出对象。
import pickle

with open('testfile.txt', 'rb') as f:
    d = pickle.load(f)
    print(d)
# output:{'score': 88, 'age': 10, 'name': 'Bob'}

我们下期见!~


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章