Python 的优势在哪里?

Python 的优势在哪里?

跨境物流行业,每日从运输监控系统(TMS)中生成条形码的单号,仓库需要根据这个单号生成条形码图片,再下载打印出来,贴到包裹上。

效果如下:

起初,仓库的工作人员是去网上找了一些所谓「在线条形码生成工具」的网站,输入单号,生成条形码。

还别说,这倒是可以生成出条形码,用扫描枪也能扫出单号。

但有两个核心问题没有解决,第一个是带水印,第二个是无法批量生成,网站一次只能生成一个条形码,而仓库一天至少要打好几千个条形码,使用网站显然满足不了仓库的需求。

用户简单说完需求,我脑海里先浮现出了三个简单而又重要的问题:

第一问:仓库的工作人员如何输入单号?

第二问:输出的图片放到什么位置?

第三问:条形码的具体形式,它的编码格式、尺寸、长宽高、分辨率等等是什么?

看到这里停一停,想想如果是你拿到这三个问题,你会怎么解决?

现在一个个解决!

第一个问题,仓库的工作人员如何输入单号?

这个通过和客户沟通得知,他们是每日的单号是通过系统导出的,平常就是最简单粗暴的复制粘贴,不是逐个输入。了解完使用场景,发现这是最简单的IO操作(文件读写),那解决的方式就很清晰了,让工作人员将单号复制到txt文本文件中,程序获取数据的方式,就是读取这个文本文件,以「行」作为分割。

第二个问题,输出的图片放到什么位置?

获取用户输入的数据,是IO操作中的Input;将生成后的图片输出为新文件,则是IO操作中的Output。

输出后的图片文件,全部放在项目的根目录下,单号作为图片的文件名,工作人员直接全选,打印即可,这样清晰易懂,简洁明了。

第三个问题,条形码的具体形式,它的编码格式、尺寸、长宽高、分辨率等等是什么?

客户最初的描述,是比较抽象的,很多东西他知道大概样子,但是说不清具体细节,而开发人员负责具体实现,因此必须对客户需求,有明确的预期。

就好像顾客去私人面馆点面,说来一碗面,小时候吃的那种。这时候,厨师需要明确顾客要的是什么面,是干面、汤面、方便面?是大碗、中碗;还是小碗、迷你碗?辣椒、香菜、胡椒要不要?等等还有很多的细节,做完前越明确,那么做完后就与顾客的期望越近,返工的概率就越小。

这一点我追着问,确定了条形码的格式是Code128,打印纸的尺寸是100mm * 100mm,长宽高无具体要求,扫描枪只要能扫出即可,分辨率至少300DPI,越清晰越好,这样兼容老的扫描设备,也允许更长的扫描距离。

参照图:

人生苦短,我用Python。

从应用场景和开发速度上,毫无疑问是Python,有专门的python-barcode库,以及生成图片的Pillow库。

初始化完项目,在命令行里输入两行命令,安装必要的库,就能进行开发了。

pip install python-barcode

pip install Pillow

这里采用面向对象的风格,定义了一个名为BarcodeGenerator的类,它负责读取包含数据的文本文件,为每个数据条目生成条形码,并将它们保存为图像文件。只接受两个参数,一个是输入的txt文本文件,一个是输出文件夹的名称。

这个类结构既简单又清晰,除了input_file和output_folder 这两个成员变量,还有一个构造函数,以及ensure_output_folder(确保输出文件夹存在)、read_codes(读取条形码数据)、generate_barcode(生成单个条形码)、generate_all_barcodes(批量生成条形码)这四个方法。

BarcodeGenerator类的构造函数接受两个参数:input_file(包含要生成条形码的数据的txt文件路径)和output_folder(用于存放生成后条形码图像的文件夹路径)。

ensure_output_folder方法用于检查指定的输出文件夹是否存在,如果不存在,则创建它。用户无需手动创建所需的目录。

这个方法看似有些多余,但实则增加了程序的健壮性。

这也是来自实际部署中的教训,因为有时候,会忘记创建输出后的文件夹,导致程序报错,虽然手动创建文件夹也可以,但终归不太够优雅,尤其是文件夹名称是比较长的英语单词的时候,因此不如在程序中干脆自动创建好,这也是Python中很基础的使用os库创建文件夹的方法。

read_codes方法从指定的txt文件中读取数据。

这是读取文件内容的基本操作,它打开输入文件,逐行读取内容,并返回一个包含所有行数据的列表。

这段代码是核心,用来生成条形码。

generate_barcode方法接受一个数据字符串,使用python-barcode库生成对应的条形码,并将其保存为图像文件。我们在这里按照客户要求,使用code128格式。

先看第一行代码:

接着,filename = os.path.join(self.output_folder, code_data) 指定生成后的图片所存放的文件夹。

接下来,最重要的就是code_writer_options里的参数了,直接决定生成条码的效果:

generate_all_barcodes方法读取所有数据行,并为每一行调用generate_barcode方法来生成条形码。

从里先拿到所有的条形码数据,再用for循环遍历列表,对每个单号逐个调用generate方法,生成条形码。

写完了类,直接在主函数中调用即可,传入输入的txt文件和输出的文件夹名称。

可以看到,一共只有两行代码,非常简洁,这也是采用面向对象风格编写代码的优势之一。

右边是txt中的单号,左边是保存生成后条形码的barcode文件夹。

生成效果:

完整代码,算上导入包与注释,一共55行:

整个代码非常简单,执行效果也达到了用户期待的效果,打印出来后,仓库直接投入使用。

这也可以看出Python的优势,从了解完需求,到开发完毕,到最后部署到客户的机器上投入使用,只用了不到1个小时,开发效率很高,客户也很满意,客观上降低了仓库的运营成本,原本每天可能要几个小时的事,现在几秒钟就处理完了。

这段代码,还存在一些优化的空间,比如将参数配置化,做到数据与逻辑的分离。把参数放到配置文件里,而不是将数据写死在代码里,这样用户可以自行选择编码格式、字体、分辨率等,各个仓库可以根据自己的情况进行调整。

还有两点是为了演示做的一些妥协,在实际开发中应当避免:

对于个人使用场景,还可以使用Python快速制作个人二维码: