模块概念

什么是模块

常见的场景:一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀。

但其实import加载的模块分为四个通用类别: 

  1 使用python编写的代码(.py文件)

  2 已被编译为共享库或DLL的C或C++扩展

  3 包好一组模块的包

  4 使用C编写并链接到python解释器的内置模块

为何要使用模块?

如果你退出python解释器然后重新进入,那么你之前定义的函数或者变量都将丢失,因此我们通常将程序写到文件中以便永久保存下来,需要时就通过python test.py方式去执行,此时test.py被称为脚本script。

随着程序的发展,功能越来越多,为了方便管理,我们通常将程序分成一个个的文件,这样做程序的结构更清晰,方便管理。这时我们不仅仅可以把这些文件当做脚本去执行,还可以把他们当做模块来导入到其他的模块中,实现了功能的重复利用。

常用模块一

collections模块

在内置数据类型(dict、list、set、tuple)的基础上,collections模块还提供了几个额外的数据类型:Counter、deque、defaultdict、namedtuple和OrderedDict等。

1.namedtuple: 生成可以使用名字来访问元素内容的tuple

2.deque: 双端队列,可以快速的从另外一侧追加和推出对象

3.Counter: 计数器,主要用来计数

4.OrderedDict: 有序字典

5.defaultdict: 带有默认值的字典

  namedtuple

namedtuple: 生成可以使用名字来访问元素内容的tuple.

我们知道tuple可以表示不变集合,例如,一个点的二维坐标就可以表示成:

p = (1, 2)

但是,看到(1, 2),很难看出这个tuple是用来表示一个坐标的。

这时,namedtuple就派上了用场:

from collections import namedtuple
Point = namedtuple('point',['x','y'])
p = Point(1,2)
print(p.x)
print(p.y)
# print(p.y+p.x)
print(p[0]+p[1])
p = p._replace(x=100,y = 30)#更改值
print(p)

类似的,如果要用坐标和半径表示一个圆,也可以用namedtuple定义:

Circle = namedtuple('circle',['x','y','r'])
c = Circle(0,0,2)
print(c.x)
print(c[2])#索引
c = c._replace(x=2,y=2,r=4)
print(c)

  deque

deque: 双端队列,可以快速的从另外一侧追加和推出对象

使用list存储数据时,按索引访问元素很快,但是插入和删除元素就很慢了,因为list是线性存储,数据量大的时候,插入和删除效率很低。

deque是为了高效实现插入和删除操作的双向列表,适合用于队列和栈:

deque除了实现list的append()pop()外,还支持appendleft()popleft(),这样就可以非常高效地往头部添加或删除元素。

from collections import deque
q = deque([1,2,3,4,5])
q.append(['lets get it',6])
q.append(7)
q.appendleft(0)
q.insert(0,-1)
print(q.pop())
print(q.popleft())
print(q.index(['lets get it',6]))
print(q)
# for i in q:
# print(i)

  queue

队列,先进先出

import queue
q = queue.Queue()
q.put([1,2,3])
q.put(6)
print(q)
print(q.get())#[1,2,3]
print(q.get())#
# print(q.get())#取不到,阻塞
print(q.qsize())#元素个数

  OrderedDict

有序字典

使用dict时,Key是无序的。在对dict做迭代时,我们无法确定Key的顺序。

如果要保持Key的顺序,可以用OrderedDict

from collections import OrderedDict
d = dict([('k1',1),('k2',2),('k3',3)])
print(d)#普通字典,key无序
od = OrderedDict([('k1',1),('k2',2),('k3',3)])
print(od)#OderedDict的key有序

注意,OrderedDict的Key会按照插入的顺序排列,不是Key本身排序:

from collections import OrderedDict
od1 = OrderedDict()
od1['x'] = 1
od1['y'] = 2
od1['z'] = 3
print(od1.keys())

  defaultdict

有如下值集合 [11,22,33,44,55,66,77,88,99,90...],将所有大于 66 的值保存至字典的第一个key中,将小于 66 的值保存至第二个key的值中。

即: {'k1': 大于66 'k2': 小于66}

 一、普通字典方法

values = [11, 22, 33,44,55,66,77,88,99,90]
my_dict = {}
for value in values:
if value>66:
if 'k1' in my_dict:#python3字典无has_key方法
# if my_dict.has_key('k1'):
my_dict['k1'].append(value)#key存在,就向列表中添加value
else:
my_dict['k1'] = [value]#key不存在就创建一个列表存储value
else:
if 'k2' in my_dict:
# if my_dict.has_key('k2'):
my_dict['k2'].append(value)
else:
my_dict['k2'] = [value]
print(my_dict)

二、defaultdict字典解决方法

from collections import defaultdict
values = [11, 22, 33,44,55,66,77,88,99,90]
d = defaultdict(list)
for value in values:
if value > 66:
d['k1'].append(value)
else:
d['k2'].append(value)
print(d)

注意:使用dict时,如果引用的Key不存在,就会抛出KeyError。如果希望key不存在时,返回一个默认值,就可以用defaultdict

from collections import defaultdict
di = defaultdict(lambda :'hello')
di['k'] = ''
di['j']
print(di)

  Counter

Counter类的目的是用来跟踪值出现的次数。它是一个无序的容器类型,以字典的键值对形式存储,其中元素作为key,其计数作为value。计数值可以是任意的Interger(包括0和负数)。Counter类和其他语言的bags或multisets很相似

from collections import Counter
c = Counter('abcabcabcasdfsdfddddd')
print(c)
c1 = Counter([1,2,3,2,1,3,45612])
print(c1)

时间模块

关于

和时间有关系的我们就要用到时间模块。在使用模块之前,应该首先导入这个模块。

#常用方法
1.time.sleep(secs)
(线程)推迟指定的时间运行。单位为秒。
2.time.time()
获取当前时间戳

表示时间的三种方式

在Python中,通常有这三种方式来表示时间:时间戳、元组(struct_time)、格式化的时间字符串:

(1)时间戳(timestamp) :通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。我们运行“type(time.time())”,返回的是float类型。

(2)格式化的时间字符串(Format String): ‘2008-08-08’

%y 两位数的年份表示(00-99)
%Y 四位数的年份表示(000-9999)
%m 月份(01-12)
%d 月内中的一天(0-31)
%H 24小时制小时数(0-23)
%I 12小时制小时数(01-12)
%M 分钟数(00=59)
%S 秒(00-59)
%a 本地简化星期名称
%A 本地完整星期名称
%b 本地简化的月份名称
%B 本地完整的月份名称
%c 本地相应的日期表示和时间表示
%j 年内的一天(001-366)
%p 本地A.M.或P.M.的等价符
%U 一年中的星期数(00-53)星期天为星期的开始
%w 星期(0-6),星期天为星期的开始
%W 一年中的星期数(00-53)星期一为星期的开始
%x 本地相应的日期表示
%X 本地相应的时间表示
%Z 当前时区的名称
%% %号本身

python中时间日期格式化符号:

(3)元组(struct_time) :struct_time元组共有9个元素共九个元素:(年,月,日,时,分,秒,一年中第几周,一年中第几天等)

 

首先,我们先导入time模块,来认识一下python中表示时间的几种格式:

import time
print(time.time())#时间戳
print(time.strftime('%Y-%m-%d %H:%M:%S'))#时间字符串,字符串格式化
print(time.localtime())
print(time.localtime(2000000000))#将时间戳转换为struct_time

小结:时间戳是计算机能够识别的时间;时间字符串是人能够看懂的时间;元组则是用来操作时间的

几种格式之间的转换

import time
#时间戳-->结构化时间
#time.gmtime(时间戳) UTC时间,与英国伦敦当地时间一致
#time.localtime(时间戳) 当地时间
print(time.gmtime(150))
print(time.localtime(150))
#结构化时间-->时间戳
#time.mktime(结构化时间)
t = time.localtime(150)
print(time.mktime(t))

import time
#结构化时间-->字符串时间
#time.strftime("格式定义","结构化时间") 结构化时间参数若不传,则显示当前时间
print(time.strftime('%Y-%m-%d %X'))
print(time.strftime('%Y-%m-%d',time.localtime(150)))
#字符串时间-->结构化时间
#time.strptime(时间字符串,字符串对应格式)
print(time.strptime('2018/10/01','%Y/%m/%d'))

import time
#结构化时间 --> %a %b %d %H:%M:%S %Y串
#time.asctime(结构化时间) 如果不传参数,直接返回当前时间的格式化串
print(time.asctime())
print(time.asctime(time.localtime(150)))
#时间戳 --> %a %b %d %H:%M:%S %Y串
#time.ctime(时间戳) 如果不传参数,直接返回当前时间的格式化串
print(time.ctime())
print(time.ctime(150))

计算时间间隔

#时间差
import time
#字符串转成结构化
str_time1 = time.strptime('2018-12-8 22:00:00','%Y-%m-%d %H:%M:%S')#前一天时间
str_time2 = time.strptime('2018-12-9 8:00:00','%Y-%m-%d %H:%M:%S')#今天时间
#结构化转成时间戳
time1 = time.mktime(str_time1)
time2 = time.mktime(str_time2)
t = time2 - time1#时间戳差
print(t) #时间戳转回结构化
t1 = time.gmtime(time2 - time1)
#结构化转回字符串
t2 = time.strftime('%H:%M:%S',time.gmtime(t))
print('时间间隔为:',t2)

random模块

import random
# 随机小数
print(random.random())#大于0小于1 之间的小数
print(random.uniform(1,3))#大于1小于3的小数
#随机整数
print(random.randint(1,5))#大于等于1且小于等于5之间的整数
print(random.randrange(1,10,2))#大于等于1且小于等于10之间的奇数

import random
#随机选择一个返回
print(random.choice(['libai','dufu','baijuyi']))
#随机选择多个返回,返沪的个数为函数的第二个参数
print(random.sample(['red','yellow','white','black','pink','blue'],3))
#打乱列表顺序
li = [1,2,3,4,5,6]
random.shuffle(li)#没有返回值
print(li)

os模块

os模块是与操作系统交互的一个接口

os.makedirs('dirname1/dirname2')    可生成多层递归目录
os.removedirs('dirname1') 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
os.mkdir('dirname') 生成单级目录;相当于shell中mkdir dirname
os.rmdir('dirname') 删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
os.listdir('dirname') 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
os.remove() 删除一个文件
os.rename("oldname","newname") 重命名文件/目录
os.stat('path/filename') 获取文件/目录信息 os.system("bash command") 运行shell命令,直接显示
os.popen("bash command).read() 运行shell命令,获取执行结果
os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径
os.chdir("dirname") 改变当前脚本工作目录;相当于shell下cd os.path
os.path.abspath(path) 返回path规范化的绝对路径
os.path.split(path) 将path分割成目录和文件名二元组返回
os.path.dirname(path) 返回path的目录。其实就是os.path.split(path)的第一个元素
os.path.basename(path) 返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素
os.path.exists(path) 如果path存在,返回True;如果path不存在,返回False
os.path.isabs(path) 如果path是绝对路径,返回True
os.path.isfile(path) 如果path是一个存在的文件,返回True。否则返回False
os.path.isdir(path) 如果path是一个存在的目录,则返回True。否则返回False
os.path.join(path1[, path2[, ...]]) 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
os.path.getatime(path) 返回path所指向的文件或者目录的最后访问时间
os.path.getmtime(path) 返回path所指向的文件或者目录的最后修改时间
os.path.getsize(path) 返回path的大小

注意:os.stat('path/filename')  获取文件/目录信息 的结构说明

stat 结构:

st_mode: inode 保护模式
st_ino: inode 节点号。
st_dev: inode 驻留的设备。
st_nlink: inode 的链接数。
st_uid: 所有者的用户ID。
st_gid: 所有者的组ID。
st_size: 普通文件以字节为单位的大小;包含等待某些特殊文件的数据。
st_atime: 上次访问的时间。
st_mtime: 最后一次修改的时间。
st_ctime: 由操作系统报告的"ctime"。在某些系统上(如Unix)是最新的元数据更改的时间,在其它系统上(如Windows)是创建时间(详细信息参见平台的文档)。

stat 结构

os.sep    输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/"
os.linesep 输出当前平台使用的行终止符,win下为"\r\n",Linux下为"\n"
os.pathsep 输出用于分割文件路径的字符串 win下为;,Linux下为:
os.name 输出字符串指示当前使用平台。win->'nt'; Linux->'posix'

os模块的属性

sys模块

sys模块是与Python解释器交互的一个接口

sys.argv           命令行参数List,第一个元素是程序本身路径
sys.exit(n) 退出程序,正常退出时exit(0),错误退出sys.exit(1)
sys.version 获取Python解释程序的版本信息
sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform 返回操作系统平台名称
import sys
try:
sys.exit(1)
except SystemExit as e:
print(e)

异常处理和status

序列化模块

概念

什么叫序列化——将原本的字典、列表等内容转化成一个字符串的过程就是序列化。

比如,我们在python代码中计算的一个数据需要给另外一段程序使用,那我们怎么给?
现在我们能想到的方法就是存在文件里,然后另一个python程序再从文件里读出来。
但是我们都知道,对于文件来说是没有字典这个概念的,所以我们只能将数据转换成字典放到文件中。
你一定会问,将字典转换成一个字符串很简单,就是str(dic)就可以办到了,为什么我们还要学习序列化模块呢?
没错序列化的过程就是从dic 变成str(dic)的过程。现在你可以通过str(dic),将一个名为dic的字典转换成一个字符串,
但是你要怎么把一个字符串转换成字典呢?
聪明的你肯定想到了eval(),如果我们将一个字符串类型的字典str_dic传给eval,就会得到一个返回的字典类型了。
eval()函数十分强大,但是eval是做什么的?e官方demo解释为:将字符串str当成有效的表达式来求值并返回计算结果。
BUT!强大的函数有代价。安全性是其最大的缺点。
想象一下,如果我们从文件中读出的不是一个数据结构,而是一句"删除文件"类似的破坏性语句,那么后果实在不堪设设想。
而使用eval就要担这个风险。
所以,我们并不推荐用eval方法来进行反序列化操作(将str转换成python中的数据结构

为什么要有序列化模块

序列化的目的

1、以某种存储形式使自定义对象持久化

2、将对象从一个地方传递到另一个地方

3、使程序更具维护性

json模块

JSON (JavaScript Object Notation) 是一种轻量级的数据交换格式。

Json模块提供了四个功能:dumps、dump、loads、load

Python3 中可以使用 json 模块来对 JSON 数据进行编解码,它包含了两个函数:

  • json.dumps(): 对数据进行编码。
  • json.loads(): 对数据进行解码。

在json的编解码过程中,python 的原始类型与json类型会相互转换,具体的转化对照如下:

Python 编码为 JSON 类型转换对应表:

JSON 解码为 Python 类型转换对应表:

json.dumps 与 json.loads(字符串)

import json
dic = {'red':'apple','yellow':'orange'}
str_dic = json.dumps(dic)#序列化,将字典转化成字符串
print(type(str_dic),str_dic)
#注意,json转换完的字符串类型的字典中的字符串是由""表示的 dic1 = json.loads(str_dic)#反序列化
#注意,要用json的loads功能处理的字符串类型的字典中的字符串必须由""表示
print(type(dic1),dic1)

json.dump 与 json.load(文件)

如果你要处理的是文件而不是字符串,你可以使用 json.dump() 和 json.load() 来编码和解码JSON数据。

import json
dic = {'red':'apple','yellow':'orange'}
#写入数据,dump方法接收一个文件句柄,直接将字典转换成json字符串写入文件
with open('f.test','w') as f:
json.dump(dic,f)
#读取数据,load方法接收一个文件句柄,直接将文件中的json字符串转换成数据结构返回
with open('f.test') as f:
f1 = json.load(f)
print(type(f1),f1)

dump(ensure_ascii)

如果ensure_ascii为true(默认值),则保证输出将所有传入的非ASCII字符转义。如果ensure_ascii为false,则这些字符将按原样输出。

import json
f = open('f.test','w',encoding='utf-8')
json.dump({'国家':'中国'},f)
# ret = json.dumps({'国家':'中国'})
# f.write(ret+'\n')#一行一行的写进去
json.dump({'国籍':'美国'},f,ensure_ascii=False)
# ret = json.dumps({'国籍':'美国'},ensure_ascii=False)
# f.write(ret+'\n')
f.close()
with open('f.test',encoding='utf-8') as f:
print(f.readlines())

dump(其他参数)

ident:

如果indent是非负整数或字符串,那么JSON数组元素和对象成员将使用该缩进级别进行漂亮打印。缩进级别为0,为负,或""仅插入换行符。 None(默认值)选择最紧凑的表示。使用正整数缩进缩进每个级别的许多空格。如果indent是一个字符串(例如"\t"),则该字符串用于缩进每个级别。

 sort_keys:

如果sort_keys为true,则字典的输出将按键排序。(默认值:)False

import json
dic = dic = {'a':'apple','b':'orange','c':'banana','d':'others'}
s = json.dumps(dic,indent='\t',sort_keys=True)
print(s)

pickle模块

json & pickle 模块

用于序列化的两个模块

  • json,用于字符串和Python数据类型间进行转换
  • pickle,用于python特有的类型和python数据类型间进行转换

pickle模块提供了四个功能:dumps、dump(序列化,存)、loads(反序列化,读)、load  (不仅可以序列化字典,列表...可以把python中任意的数据类型序列化

import pickle
dic = {'red':'apple','yellow':'orange'}
s = pickle.dumps(dic)
print(type(s),s)#二进制bytes类型
s1 = pickle.loads(s)
print(type(s1),s1)

import pickle
import time
struc_time = time.localtime(150)
print(struc_time)
f = open('pickle_file','wb')#要以bytes类型写进文件
pickle.dump(struc_time,f)
f.close() f = open('pickle_file','rb')
struc_time1 = pickle.load(f)
print(struc_time1)

既然pickle如此强大,为什么还要学json呢?
说明一下,json是一种所有的语言都可以识别的数据结构。
如果我们将一个字典或者序列化成了一个json存在文件里,那么java代码或者js代码也可以拿来用。
但是如果用pickle进行序列化,其他语言就不能读懂这是什么了~
所以,如果要序列化的内容是列表或者字典,那就最好使用json模块
但如果出于某种原因你不得不序列化其他的数据类型,而未来你还会用python对这个数据进行反序列化的话,那么就可以使用pickle

shelve模块

shelve是一个简单的数据存储方案,类似key-value数据库,可以很方便的保存python对象,其内部是通过pickle协议来实现数据序列化。shelve只有一个open()函数,这个函数用于打开指定的文件(一个持久的字典),然后返回一个shelf对象。shelf是一种持久的、类似字典的对象。它与“dbm”的不同之处在于,其values值可以是任意基本Python对象--pickle模块可以处理的任何数据。这包括大多数类实例、递归数据类型和包含很多共享子对象的对象。keys还是普通的字符串。

open(filename, flag='c', protocol=None, writeback=False)

flag 参数表示打开数据存储文件的格式,可取值与dbm.open()函数一致:

protocol 参数表示序列化数据所使用的协议版本;

writeback 参数表示是否开启回写功能。

我们可以把shelf对象当dict来使用--存储、更改、查询某个key对应的数据,当操作完成之后,调用shelf对象的close()函数即可。当然,也可以使用上下文管理器(with语句),避免每次都要手动调用close()方法。

import shelve
f = shelve.open('shelve_file')
f['key'] = {'int':10, 'float':9.5, 'string':'Sample data'} #直接对文件句柄操作,就可以存入数据
s = f['key']
print(s)
f.close()

import shelve
f = shelve.open('shelve_file')
f['name'] = 'tom'
f['age'] = 18
f['hobby'] = ['movie','basketball','swim']
f['other_info'] = {'phone':'','address':'beijing'}
f.close()
with shelve.open('shelve_file') as f:
for key,value in f.items():
print(key,'-->',value)

pass

python学习日记(常用模块)的更多相关文章

  1. Python学习 :常用模块(二)

    常用模块(二) 四.os模块 os模块是与操作系统交互的一个接口,用于对操作系统进行调用 os.getcwd() # 提供当前工作目录 os.chdir() # 改变当前工作目录 os.curdir( ...

  2. Python学习笔记-常用模块

    1.python模块 如果你退出 Python 解释器并重新进入,你做的任何定义(变量和方法)都会丢失.因此,如果你想要编写一些更大的程序,为准备解释器输入使用一个文本编辑器会更好,并以那个文件替代作 ...

  3. Python学习 :常用模块(三)----- 日志记录

    常用模块(三) 七.logging模块 日志中包含的信息应有正常的程序访问日志,还可能有错误.警告等信息输出 python的 logging 模块提供了标准的日志接口,你可以通过它存储各种格式的日志, ...

  4. python 学习分享-常用模块篇

    模块 就是前人给你造的轮子,你开车就好!!! 常用模块有: time模块 random模块 os模块 sys模块 shutil模块 json  &  picle模块 shelve模块 xml处 ...

  5. Python学习-day5 常用模块

    day5主要是各种常用模块的学习 time &datetime模块 random os sys shutil json & picle shelve xml处理 yaml处理 conf ...

  6. Python学习 :常用模块(四)----- 配置文档

    常用模块(四) 八.configparser 模块 官方介绍:A configuration file consists of sections, lead by a "[section]& ...

  7. Python学习 :常用模块(一)

    常用模块(一) 一.时间(time)模块 时间戳 (Timestamp):时间戳表示的是从1970年1月1日00:00:00为计时起点,到当前的时间长度 import time print(help( ...

  8. python学习日记(模块导入)

    什么是模块? 常见的场景:一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀. 但其实import加载的模块分为四个通用类别: 1 使用python编写的代码(.p ...

  9. 06 python学习笔记-常用模块(六)

    一.  模块.包 1.什么是模块? Python 模块(Module),是一个 Python 文件,以 .py 结尾,包含了 Python 对象定义和Python语句,是用来组织代码的.模块能定义函数 ...

  10. Python学习之==>常用模块

    一.string模块 import string print(string.ascii_letters) # 所有大小写字母 print(string.ascii_lowercase) # 所有小写字 ...

随机推荐

  1. 用bat批处理程序通过DOS命令行删除所有的空文件夹

    用过gothub或者码云的同学都知道,不包含任何文件的空文件夹上传提交时不被允许的.当然你可以在空文件下创建.keep文件(或.gitkeep文件),然后就可以上传了. 但是如果空文件夹比较多,并且我 ...

  2. 学习笔记—XML

    XML XML简介 XML指可扩展标记语言(EXtensible Markup Language),是一种标记语言. XML是一种灵活的语言,标签没有被预定义,需要自行定义标签. 通常,XML被用于信 ...

  3. 通过JS动态的修改HTML元素的样式和增添标签元素等

    一. 通过JS动态的修改HTML元素的样式   1. 要想在js中动态的修改HTML元素的样式,首先需要写document,    document我们称之为文档对象,这个对象中保存了当前网页中所有的 ...

  4. 解决Angular2 (SystemJS) XHR error (404 Not Found) loading traceur

    初学Angular2,跟着Angular2中文网学到HTTP这一节时出现了一个异常: GET http://localhost:3000/traceur 404 (Not Found) Error: ...

  5. 【已采纳】charles工具使用心得

    1.下载charles 可以去charles官网下载,下载地址:http://www.charlesproxy.com/download/    根据自己的操作系统下载对应的版本,然后进行安装,然后打 ...

  6. django csrf token添加

    #views.py from django.shortcuts import render_to_response, RequestContext from django.views.decorato ...

  7. pyspider+PhantomJS的代理设置

    环境:pyspider0.3.9 PhantomJS2.1.1,均为最新版 进程用supervisor托管的. 其中需要加的几个地方: webui进程: pyspider -c config.json ...

  8. webapi返回文件流

    逻辑说明 webapi返回类型为IHttpActionResult接口,内部方法返回HttpResponseMessage. public interface IHttpActionResult { ...

  9. 【shell实例】定时21:00-21:05,循环调用DSQL脚本,其它时段自动退出

    1.功能描述: 每日21:00定时调起test.sh,循环调起DSQL脚本test.dsql,直到21:05程序自动退出,捕获日志到相应log文件中. 2.日志文件: (1)日期.log文件中含Err ...

  10. jeecg入门操作—一对多表单开发

    一.创建主表 创建订单主表(torder_main)  二.创建附表客户信息表(torder_customer) 设置附表页面外键不可见 设置附表外键  三.创建附表机票 信息表(torder_tic ...