Python小项目 —— 企业编码生成系统

本文最后更新于:2020年5月17日 晚上

概览:Python控制台项目,比较简单。

简介

《Python项目开发案例集锦》是我在20年疫情期间发现的一本书,介绍了好多个小项目,以及整本书的源码和可执行程序。之前简单学过一点Python的语法之后,再也没有用过Python了,正巧用这里面的代码练练手。

这个项目:企业编码生成器,是一个控制台项目,接收用户的命令生成指定格式的编码或者防伪码,存储到对应文件之中,此外还有生成条形码以及二维码的功能。

这个项目实际上用到的东西包括列表、集合、随机数的生成、文件目录的操作以及常规流程控制的掌握,总体来说没有什么难度,二维码以及条形码模块使用的方式也非常的简单。

项目功能及演示

1.生成6位数字防伪编码 (213563型):模拟手机上的6位数字验证码。

2.生成9位系列产品数字防伪编码(879-335439型):前3位表示产品类型,后六位代表同一类型的随机编号。

3.生成25位混合产品序列号(B2R12-N7TE8-9IET2-FE35O-DW2K4型):模拟Windows激活的序列号。

4.生成含数据分析功能的防伪编码(5A61M053D):包含三个字母编码,字母编码有着相对位置的要求,第一个字母代表地区,第二个字母代表产品颜色。第三个字母代表产品批次。

5.智能批量生成带数据分析功能的防伪码:对4功能的扩充,需要先编辑plcode.mri文件,然后会根据文件批量生成。

6.后续补加生成防伪码:对4、5功能生成的编码文件的扩充。

7.EAN-13条形码批量生成:生成超市常用的EAN-13条形码,生成的条形码图片保存在文件夹ean13code

8.二维码批量输出:生成常见的二维码,生成的二维码图片保存在文件夹qrcode

部分结果展示:

说明

下面的代码并未完全仿照原书的代码,对比原书的代码,我的代码删掉了许多无用的变量,删掉了tkinter模块,因为这个模块弹出的图形界面太卡了。再然后是每个功能生成编码的时候都使用set集合进行去重,会和原先的代码有很大差别。

项目的结构
## 代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
import os,random,time
import qrcode # 二维码模块
from pystrich.ean13 import EAN13Encoder #条形码模块

# 初始化数据
number = "1234567890"
letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"

def mainmenu():
'''企业编码管理系统主菜单'''
print("""\033[1;35m
****************************************************************
企业编码生成系统
****************************************************************
1.生成6位数字防伪编码 (213563型)
2.生成9位系列产品数字防伪编码(879-335439型)
3.生成25位混合产品序列号(B2R12-N7TE8-9IET2-FE35O-DW2K4型)

4.生成含数据分析功能的防伪编码(5A61M053D)
5.智能批量生成带数据分析功能的防伪码
6.后续补加生成防伪码

7.EAN-13条形码批量生成
8.二维码批量输出
0.退出系统
================================================================
说明:通过数字键选择菜单
================================================================
\033[0m""")

def input_validation(insel):
'''判断在主菜单的输入是否非法'''
if str.isdigit(insel): # 验证是否是数字
insel = int(insel) # 这里需要将insel转成数字!
return insel
else:
print("输入非法,请重新输入")
return 0

def mkdir(path):
'''创建文件夹'''
isexists = os.path.exists(path)
if not isexists:
os.mkdir(path)

def openfile(filename):
'''读取文本文件'''
f = open(filename)
fllist = f.read()
f.close()
return fllist

def inputbox(showstr, showorder, length):
"""
输入验证判断
:param showstr: 输入提示文字
:param showorder: 输入内容的类型,1.数字,不限位数,2.字母,3.数字且有位数要求
:param length: 输入内容的长度
:return:
"""
instr = input(showstr)
if len(instr) != 0:
if showorder == 1:
if str.isdigit(instr): # 验证是否是数字
if instr == 0:
print("输入为0,请重新输入!")
return '0'
else:
return instr
else: # 如果输入不是数字
print("输入非法,请重新输入!")
return '0'
if showorder == 2:
if str.isalpha(instr): # 验证输入的内容是否是字母
if len(instr) != length: # 输入位数不符
print("必须输入" + str(length) + "个字母,请重新输入!")
return '0'
else:
return instr
if showorder == 3:
if str.isdigit(instr): # 验证是否是数字
if len(instr) != length:
print("必须输入" + str(length) + "个数字,请重新输入!")
return '0'
else:
return instr
else:
print("输入非法,请重新输入!")
return '0'
else:
print("输入为空,请重新输入!")
return '0'

def wfile(sstr, sfile, typeis, smsg, datapath):
"""
编码输出显示,同时保存文件
:param sstr: 生成的防伪码
:param sfile: 保存防伪码的文件名
:param typeis: 是否显示输出完成的防伪码,""时显示提示框,"no"时不显示
:param smsg: 提示框显示的提示内容
:param datapath: 保存防伪码的路径
"""
mkdir(datapath)
datafile = datapath + '\\' + sfile # 设置保存防伪码的文件路径
file = open(datafile, 'w') # 打开保存防伪码文件,不存在则创建,存在则会将其覆盖掉
wrlist = sorted(list(sstr)) # 将防伪码信息赋值给
pdata = "" # 清空变量,pdata存储屏幕输出的防伪码信息
wdata = "" # 清空变量,wdata存储保存到文本文件的防伪码信息
for i in range(len(wrlist)):
wdata = str(wrlist[i].replace('[', '').replace(']', '')) # 去掉字符的中括号
wdata = wdata.replace('"', '').replace("'", "") # 去掉字符串中的引号
file.write(str(wdata))
pdata = pdata + wdata
file.close()

if typeis != "no":
print(pdata) # 输出生成的防伪码信息

print(smsg + str(len(wrlist)) + "\n防伪码文件存放位置" + datafile)

def replace_strIndex(string, char, index):
'''将字符串中指定位置的字符进行替换'''
string = list(string) # python str是不可变量,转换成列表
string[index] = char
return "".join(string) # return str(string) list转str的错误操作

def scode1(schoice):
'''生成6位数字防伪编码 (213563型)'''
incount = inputbox("\033[1;32m 请输入您要生成验证码的数量:\33[0m", 1, 0)
while int(incount) == 0: # 若输入为0则重新输入
incount = inputbox("\033[1;32m 请输入您要生成验证码的数量:\33[0m", 1, 0)

coding_set = set() # 在创建空集合的时候,只能使用set()而不能使用{},{}会创建成字典

while len(coding_set) != int(incount):
coding = ""
for k in range(6):
coding = coding + random.choice(number) # 产生随机数因子
coding = coding + "\n"
coding_set.add(coding) # 将单条防伪码添加到保存批量验证码的变量中

wfile(coding_set, "scode" + str(schoice) + ".txt", "", "已生成6位防伪码共计:", "codepath")

def scode2(schoice):
'''生成9位数字系列产品防伪编码'''
beginNum = inputbox("\033[1;32m 请输入系列产品的数字起始号码(3位):\33[0m", 3, 3)
while int(beginNum) == 0:
beginNum = inputbox("\033[1;32m 请输入系列产品的数字起始号码(3位):\33[0m", 3, 3)
beginNum = int(beginNum)

kindNum = inputbox("\033[1;32m 请输入产品系列的数量:\33[0m", 1, 0)
while int(kindNum) == 0:
kindNum = inputbox("\033[1;32m 请输入产品系列的数量:\33[0m", 1, 0)
kindNum = int(kindNum)

aloneNum = inputbox("\033[1;32m 请输入要生成的每个系列产品的防伪码数量:\33[0m", 1, 0)
while int(aloneNum) == 0:
aloneNum = inputbox("\033[1;32m 请输入要生成的每个系列产品的防伪码数量:\33[0m", 1, 0)
aloneNum = int(aloneNum)

coding_set = set() # 在创建空集合

for j in range(kindNum):
beginNum = beginNum + 1 # 更新前缀
litter_coding_set = set()
while len(litter_coding_set) != aloneNum:
coding = str(beginNum) # 每一次循环都重置coding
for m in range(6):
coding = coding + random.choice(number)
coding = coding + "\n"
litter_coding_set.add(coding)
coding_set.update(litter_coding_set)

wfile(coding_set, "scode" + str(schoice) + ".txt", "", "已生成9位系列产品防伪码共计:", "codepath")

def scode3(schoice):
'''生成25位混合产品序列号'''
incountNum = inputbox("\033[1;32m 请输入要生成的25位混合产品序列号数量:\33[0m", 1, 0)
while int(incountNum) == 0:
incountNum = inputbox("\033[1;32m 请输入要生成的25位混合产品序列号数量:\33[0m", 1, 0)
incountNum = int(incountNum)

coding_set = set() # 在创建空集合

while len(coding_set) != incountNum:
randstrtmp = ""
for k in range(5):
coding = ""
for m in range(5):
coding = coding + random.choice(letter)
if k == 4:
coding = coding + "\n"
else:
coding = coding + "-"

randstrtmp = randstrtmp + coding
coding_set.add(randstrtmp)

wfile(coding_set, "scode" + str(schoice) + ".txt", "", "已生成25位混合产品序列号共计:", "codepath")

def scode4(schoice):
'''生成含数据分析功能的防伪编码
主要由3位字母和6位数字组成,并且字母位置随机,但是首字母对应不同地区,
次字母对应产品颜色,最后的字母对应产品批次
'''
inLetter = inputbox("\033[1;32m 请输入数据分析编号的三位字母:\33[0m", 2, 3)
while not inLetter.isalpha() or len(inLetter) != 3:
inLetter = inputbox("\033[1;32m 请输入数据分析编号的三位字母:\33[0m", 2, 3)

incountNum = inputbox("\033[1;32m 请输入要生成的带数据分析功能的防伪码数量:\33[0m", 1, 0)
while int(incountNum) == 0:
incountNum = inputbox("\033[1;32m 请输入要生成的带数据分析功能的防伪码数量:\33[0m", 1, 0)
incountNum = int(incountNum)

coding_set = set() # 在创建空集合

let = [inLetter[j].upper() for j in range(3)]

while len(coding_set) != incountNum:
indexNum = "012345678" # 数字索引,不需要9
ranIndex = random.sample(indexNum, 3) # sample函数的作用是从number中获取三个不重复的值,将结果作为list返回
ranIndex = list(map(int, ranIndex))
ranIndex = sorted(ranIndex) # 对结果进行排序

myNum = ""
for k in range(9):
myNum = myNum + random.choice(number)

for n in range(3):
myNum = replace_strIndex(myNum, let[n], ranIndex[n])

myNum = myNum + "\n"
coding_set.add(myNum)

wfile(coding_set, "scode" + str(schoice) + ".txt", "", "已生成9位含数据分析功能的防伪编码共计:", "codepath")

def scode5(schoice):
'''
智能批量生成带数据分析功能的防伪码
利用文件批量生成数据
'''
file_path = "plcode.mri" # 设置默认打开的文件名称
codelist = openfile(file_path) # 读取从文件选择对话框中选择的文件
codelist = codelist.split("\n") # 把读取的内容以回车分割,饭会分割后的列表

for item in codelist:
codea = item.split(",")[0] # 将每一行按照“,”分割,逗号前的存储为防伪码标准信息
codeb = item.split(",")[1] # 将每一行按照“,”分割,逗号后的存储为防伪码生成数量

coding_set = set() # 在创建空集合

let = [codea[j].upper() for j in range(len(codea))] # 将字母转成大写

while len(coding_set) != int(codeb):
indexNumber = "012345678"
ranIndex = random.sample(indexNumber, 3) # 随机取三个不重复的数
ranIndex = list(map(int, ranIndex)) # 将ranIndex转成数字
ranIndex = sorted(ranIndex)

myNum = ""
for k in range(9):
myNum = myNum + random.choice(number)

for m in range(3):
myNum = replace_strIndex(myNum, let[m], ranIndex[m])

myNum = myNum + "\n"
coding_set.add(myNum)
wfile(coding_set, codea + "scode" + str(schoice) + ".txt", "no", "已生成9位含数据分析功能的防伪编码共计:", "codepath")

def scode6(schoice):
'''后续补加生成防伪码'''
print("\033[1;32m 本功能只针对于功能5的数据文件做添加操作!:\33[0m")
file_name = input("请输入要补加防伪码的文件名称:")
file_path = r"./codepath/" + file_name
fileData = openfile(file_path) # 获取文件数据
fileData_list = fileData.split("\n") # 将文件数据转成List
fileData_list.pop() # 文件读取的最后一行为空格,删除

for i in range(len(fileData_list)):
fileData_list[i] = fileData_list[i] + "\n"

print("之前生成的防伪码数量共计:" + str(len(fileData_list)) + "个")

fileData_set = set(fileData_list) # 将list转成set,保证元素不重复

incountNum = inputbox("\033[1;32m 请输入要补加的带数据分析功能的防伪码数量:\33[0m", 1, 0)
while int(incountNum) == 0:
incountNum = inputbox("\033[1;32m 请输入要补加的带数据分析功能的防伪码数量:\33[0m", 1, 0)
incountNum = int(incountNum)

let = [file_name[j].upper() for j in range(3)] # 获取三个字母

while len(fileData_set) - len(fileData_list) != incountNum:
indexNumber = "012345678"
ranIndex = random.sample(indexNumber, 3) # 随机取三个不重复的数
ranIndex = list(map(int, ranIndex)) # 将ranIndex转成数字
ranIndex = sorted(ranIndex)

myNum = ""
for k in range(9):
myNum = myNum + random.choice(number)

for m in range(3):
myNum = replace_strIndex(myNum, let[m], ranIndex[m])

myNum = myNum + "\n"
fileData_set.add(myNum)

print("已经新生成的防伪码数量共计:" + str(len(fileData_set) - len(fileData_list)) + "个")

wfile(fileData_set, file_name[:3] + "scode" + str(schoice) + ".txt", "no", "已生成9位含数据分析功能的防伪编码共计:", "codepath")

def scode7(schoice):
'''
实现条形码的输出
EAN-13是一种常见的条形码,多用于超市和零售市场
EAN-13: European Article Number,共计13位
前3位为国家码(中国大陆是690-695),4-7位为企业码,8-12位为商品码,第13位是校验位
校验位的计算:
1、前12位的偶数位相加
2、前12位的奇数位相加
3、将偶数位的和的三倍与奇数位的和相加
4、取出得到的和的个位
5、由10减去这个个位数,再将得到的结果取个位即可
'''

nationId = inputbox("\033[1;32m 请输入EAN-13的国家码(3位):\33[0m", 3, 3)
while int(nationId) == 0:
nationId = inputbox("\033[1;32m 请输入EAN-13的国家码(3位):\33[0m", 3, 3)

compId = inputbox("\033[1;32m 请输入EAN-13的企业码(4位):\33[0m", 3, 4)
while int(compId) == 0:
compId = inputbox("\033[1;32m 请输入EAN-13的企业码(4位):\33[0m", 3, 4)

codeNum = inputbox("\033[1;32m 请输入要生成的条形码的数量 :\33[0m", 1, 0)
while int(codeNum) == 0:
codeNum = ("\033[1;32m 请输入要生成的条形码的数量 :\33[0m", 1, 0)

codeNum = int(codeNum)

codeNum_set = set()
while len(codeNum_set) != codeNum:

sellId = "" # 商品码
for j in range(5):
sellId = sellId + random.choice(number)

sellId = nationId + compId + sellId # 商品码前缀添加国家码与企业码
# 生成校验码
oushu = 0
for k in range(0,11,2):
oushu = oushu + int(sellId[k])
jishu = 0
for k in range(1,11,2):
jishu = jishu + int(sellId[k])

jiaoyan = (10 - (oushu*3 + jishu)%10)%10

sellId = sellId + str(jiaoyan)
codeNum_set.add(sellId)

# 生成激活码,并且保存
wfile(codeNum_set, "scode" + str(schoice) + ".txt", "no", "已生成EAN-13条形码共计:", "codepath")
codeNum_list = list(codeNum_set)
mkdir("ean13code")
for index in range(codeNum):
encoder = EAN13Encoder(codeNum_list[index])
encoder.save("ean13code\\"+codeNum_list[index]+".png")

print("ean-13的全部条形码保存在"+"ean13code文件夹下")

def scode8(schoice):
codeNum = inputbox("\033[1;32m 请输入要生成的12位数字二维码的数量 :\33[0m", 1, 0)
while int(codeNum) == 0:
codeNum = ("\033[1;32m 请输入要生成的条形码的数量 :\33[0m", 1, 0)
codeNum = int(codeNum)

codeNum_set = set()
while len(codeNum_set) != codeNum:
qrRanCode = ""
for j in range(12):
qrRanCode = qrRanCode + random.choice(number)

codeNum_set.add(qrRanCode)

wfile(codeNum_set, "scode" + str(schoice) + ".txt", "no", "已生成12位数字二维码共计:", "codepath")
mkdir("qrcode")
codeNum_list = list(codeNum_set)

for j in range(len(codeNum_list)):
encoder = qrcode.make(codeNum_list[j])
encoder.save("qrcode\\"+codeNum_list[j]+".png")
return True

def mainpro():
'''
通过循环控制用户对程序功能的选择
'''
while True:
mainmenu() # 调入程序主界面菜单
choice = input("\033[1;32m 请输入您要操作的菜单选项:\33[0m") # 键盘输入需要操作的选项
if len(choice) != 0:
choice = input_validation(choice) # 验证输入是否为数字
if choice == 1:
scode1(choice)
if choice == 2:
scode2(choice)
if choice == 3:
scode3(choice)
if choice == 4:
scode4(choice)
if choice == 5:
scode5(choice)
if choice == 6:
scode6(choice)
if choice == 7:
scode7(choice)
if choice == 8:
scode8(choice)
if choice == 0:
print("正在退出系统!!")
break
else:
print("\033[1;31;40m 输入非法,请重新输入!!\033[0m")
time.sleep(2)

# 程序的执行
mainpro()

相关知识总结

列表

1
2
3
4
5
6
7
8
9
10
11
12
13
let = []
for j in range(3): #都转成大写字母
let[j] = inLetter[j].upper() # 错误写法!数组越界

#########正确的写法#############

# 法1:列表生成式
let = [inLetter[j].upper() for j in range(3)]

# 法2:append方法
let = []
for j in range(3):
let.append(inLetter[j].upper())

列表中的每个元素都是字母,转换成数字

1
2
3
indexNum = "012345678"  # 数字索引,不需要9
ranIndex = random.sample(indexNum, 3) # sample函数的作用是从number中获取三个不重复的值,将结果作为list返回
ranIndex = list(map(int, ranIndex))

字符串

替换字符串指定位置的字母

1
2
3
4
5
6
# 函数:将字符串中指定位置的字符进行替换
def replace_strIndex(string,char,index):
string = list(string) #python str是不可变量,转换成列表
string[index] = char
#return str(string) list转str的错误操作
return "".join(string)

list转str的方式

1
"".join(string)

random的用法

1
2
3
random.choice(seq) #返回列表、元组、字符串中的任意一项

random.sample(indexNum, 3) # sample函数的作用是从number中获取三个不重复的值,将结果作为list返回

set集合

使用set集合来确保无重复。但是set集合顺序不固定,不能使用索引的方式访问元素

1
2
3
4
5
6
7
8
9
10
mylet_set = {"1","2","3"} #set初始化方式一,但不能使用空的{}进行初始化,这样初始化生成的是字典
mynum_set = set() #set初始化方式二,可生成一个空的set


mynum_set.add() #增加元素
mynum_set.pop() #随机删除一个元素
mynum_set.update(mylet_set) #将两个集合合并在一起

# list --> set
mynum_list = list(mynum_set)

吐槽一下

《Python项目开发案例集锦》这本书关于这个项目的教程……,书中代码有错误的部分,与提供的源代码不匹配;关于编码不能重复的问题,前几个功能它一直都没考虑过编码重复的这个问题,到功能6的时候开始考虑了,这个真是有点随意。还有给变量起名的确不是一件容易的事情,命名真是一塌糊涂。

代码的可执行文件获取以及书籍下载

代码的可执行文件:https://pan.baidu.com/s/1YWwPQVp9CYvrGyy31CUPpw 提取码:kv7v

《Python项目开发案例集锦》书籍及源码下载:https://pan.baidu.com/s/154xVwvRV1E5U476iY_EJXw
提取码:wc8x