在reportlab的官方网站(https://www.reportlab.com/chartgallery/pie/)上给出生成各种图表的例子,对于我这种不经常跟图表打交道的人来说还是挺开眼界的,我们拿出几个做中文注释。在即将推出的reportlab的教学视频里会详细介绍每个程序,先来看都生成了哪些图表。
直方图(Bar Chart):
折线图(Line Plot):
饼形图(Pie Chart):
雷达图(Radar Chart或蛛网图Spider Chart):
散点图(Scatter Plot):
分区图(Area Chart):
生成每个图表的程序都放在独立的代码文件里,用自定义的类来完成,程序runall.py把当前文件夹下的所有生成图表的.py的程序逐个运行,生成指定类型的图表文件(可以是pdf、pict或png)。runall.py和注释如下:
# 运行代码所在目录下所有的生成图表的py程序import sysimport glob # 查找符合特定规则的文件路径名import inspect # 可以获取类和对象的参数信息def moduleClasses(mod): # moduleClasses的mod参数是引进的模块 def P(obj, m=mod.__name__, CT=type): return (type(obj)==CT and obj.__module__==m) # mod.__name__得到的模块名,比如'2-2lineChart_withMarkers' # 这里为了讲课方便,模块的名称用数字序号开头标识顺序 # 直接在程序中用import 2-2lineChart_withMarkers是会报错的 # 但动态引入就可以,比如__import__('2-2lineChart_withMarkers') # obj是模块里包括引用模块的类成员 # 比如2-2lineChart_withMarkers.py里定义的LineChart_WithMarkers # 也可能是引用的模块里的成员,比如PCMYKColor(0,0,0,24,alpha=100) # obj.__module__得到obj所在的模块名 # obj.__module__== m,m是mod.__name__,mod是调用函数给的模块 # 所以这个判断条件确保只提取给出模块的类成员 # type(obj)是obj的类型,如果是在module直接定义的类,类型是type try: return inspect.getmembers(mod, P)[0][1] # inspect.getmembers()检查第一个参数mod(module的前三个字母)的成员和值, # 这里的mod是个模块 # 如果有第二个参数P(函数名),则只返回P为真的成员和值 # inspect.getmembers(mod, P))返回: # [('ClusteredBar', )] except: return Nonedef getclass(f): return moduleClasses(__import__(f)) # import导入Python模块时,调用的是__import__()函数,只有动态加载模块时才直接使用该函数 # __import__(f)引入f, 如__import__('2-2lineChart_withMarkers') # 将2-2lineChart_withMarkers.py的内容引入 # __import__(f)返回引进模块,比如 # 调用函数moduleClasses(引入的模块),moduleClasses()函数可以把模块里定义的类取出来 # 所以函数getclass()的返回值是模块里定义的类def run(format, VERBOSE=0):# format接收声称文件的类型,比如pdf,png……# VERBOSE是冗长、啰嗦,默认为0;如果调用run()时指定为1,则会输出文件的类型 formats = format.split(',') # 假如接收到的format是' PDF, png',则format被用','分开后得到的formats为[' PDF', 'png'] for i in range(0, len(formats)): formats[i] == formats[i].strip().lower() # 剥掉列表formats的每个字符串元素左右的空格,并变成小写,formats变成['pdf', 'png'] allfiles = glob.glob('*.py') # glob.glob('*.py')将当前文件夹下的py文件名字符串取出来,放进allfiles # 比如allfiles的内容可能为['2-2lineChart_withMarkers.py', '5-1areaChart_withDynamicLabel.py', ……] allfiles.sort() # 对列表allfiles的元素进行排序 for fn in allfiles: # 进入循环一个一个文件处理 f = fn.split('.')[0] # fn.split('.')把文件名与扩展名分开,比如['2-2lineChart_withMarkers', 'py'] # 索引为0取出文件名放入变量f,即'2-2lineChart_withMarkers' c = getclass(f) # 调用自己定义的函数getclass('2-2lineChart_withMarkers') # 引进名字为f的模块或类,跟在程序首部把f引进(import)一个效果 # 返回名字为f的类或模块,比如 if c != None: # 如果fn里确实有定义的类和模块,则存放返回值的变量c就不为None print(c.__name__) # 显示fn里定义的类名称,比如LineChart_WithMarkers try: for fmt in formats: # 理论上formats是存放着文件格式字串的列表,比如[' PDF', 'png'] if fmt: # 如果列表元素不为空 c().save(formats=[fmt],outDir='.',fnRoot=c.__name__) # c是引入的fn里定义的一个类,c()是类c生成的一个对象 # 调用c类对象的方法函数save()将对象内容生成指定格式的文件 # formats=格式参数,outDir=区分名字和扩展名的符号,fnRoot=文件名 if VERBOSE: # 如果调用函数时给的VERBOSE为1 print(" %s.%s" % (c.__name__, fmt)) # 则输出文件名及格式 except: print(" COULDN'T CREATE '%s.%s'!" % (c.__name__, format)) # 出错输出提示无法生成该格式的文件,继续处理下一个if __name__ == "__main__": if len(sys.argv) == 1: # 以下情况if语句的条件为真: # 1、在pycharm(或其他集成开发环境) # 2、在终端/命令窗口进入runall.py所在目录,敲入:python3 runall.py run('pdf,pict,png') # 依次声称PDF、PICT和PNG文件类型的图表 else: try: if sys.argv[1] == "-h": # if语句条件为真的情况: # 在命令行或终端进入runall.py所在目录,运行: python3 runall.py -h # sys.argv[0]为'runall.py',sys.argv[1]为'-h' print('usage: runall.py [FORMAT] [-h]') print(' if format is supplied is should be one or more of pdf,gif,eps,png etc') print(' if format is missing the following formats are assumed: pdf,pict,png') print(' -h prints this message') else: t = sys.argv[1:] # 比如命令:python3 runall.py PDF PNG,sys.argv[1]为'PDF' # sys.argv[2]为'PNG',t的值为['PDF', 'PNG'] for f in t: run(f) # 进入循环,依次运行run('PDF')和run('PNG'),指定生成的文件类型 except: # 给出出错提示,输出跟python3 runall.py -h一样 print('usage: runall.py [FORMAT][-h]') print(' if format is supplied is should be one or more of pdf,gif,eps,png etc') print(' if format is missing the following formats are assumed: pdf,pict,png') print(' -h prints this message') raise
后面的帖子会给出一系列图表的程序和中文注释,敬请关注。