项目场景:
题主最近在写sql,因为每条语句存在大量重复字段,故考虑python脚本自动化生成sql代码,但是最后总是多一个逗号,有时候debug发现原因就出在忘记删这个结尾的逗号,故考虑想办法删掉结尾字符。
问题描述
这里拿一个最简单的场景举例,将输入的字符列表转成小写字符,并批量写出,最初的代码如下
stringlist = ["TEST1", "TEST2", "TEST3", "TEST4"]
def stringToLower(stringlist):
with open('\path\to\txt','w',encoding='utf-8') as f:
for i in range(len(stringlist)):
tmp = stringlist[i]
f.write(str(tmp)+","+"\n")
f.close()
stringToLower(stringlist)
输出:
test1,
test2,
test3,
test4,
可以看到这样写的话结尾的字符串总会多一个,
这样在后续操作时每次都要手工删除一个逗号,如果忘记删除了可能会带来后续的一系列bug,所以能不能在脚本里面加上自动删除最后一个逗号呢?
题主先在网上搜索,看到了如下的解决方案:
import os
file_old = open('D:/EEG/LXP/FRAG1/FZ_H_ch5.txt', 'rb+')
n = 6
# 定位倒数第n个字符
file_old.seek(-n, os.SEEK_END)
# 截断之后的数据
file_old.truncate()
file_old.close()
移动指针到倒数第n个字符,然后截断
于是简单的修改:
def stringToLower(stringlist):
with open('\path\to\txt','w',encoding='utf-8') as f:
for i in range(len(stringlist)):
tmp = stringlist[i]
f.write(str(tmp)+","+"\n")
f.seek(-1, os.SEEK_END)
f.truncate()
f.close()
但是!!!!!!!!!!!!!出现如下报错
UnsupportedOperation: can't do nonzero end-relative seeks
网上查询,说必须将权限加上b
于是修改权限为'wb+'
,结果又报错
ValueError: binary mode doesn't take an encoding argument
很明显,和encoding
编码又冲突了,删去encoding='utf-8'
,以为要成功了,好家伙,又报了新的错:
TypeError: a bytes-like object is required, not 'str'
很明显,不编码的话字符串根本都没法解析,编码的话又不支持binary mode,进而没法使用f.seek(),此时答主非常崩溃,这些错误仿佛形成了一个闭环,改来改去最后进了死胡同
但是我转念一想,如果我将写入操作和删除最后一个字符的操作分开,那么不就不矛盾了吗!
说干就干:
def stringToLower(stringlist):
with open('\path\to\txt','w',encoding='utf-8') as f:
for i in range(len(stringlist)):
tmp = stringlist[i]
f.write(str(tmp)+","+"\n")
f.close()
with open('\path\to\txt','rb+',encoding='utf-8') as f:
f.seek(-1, os.SEEK_END)
f.truncate()
f.close()
很好,终于不报错了,但是当我打开输出的txt文档发现,最后一个逗号并没有删除掉(令人吐血),代码没有问题,那就是我的逻辑出问题了。再仔细看一下写入的代码,发现其实在逗号后面,还有一个换行符\n
,那么把-1改成-2就行了吗?当然不行,在一行的末尾,其实是有两个字符\r \n
一个是回车一个是换行,所以要改成-3才将指针移到逗号前面,
所以最后的代码如下:
def stringToLower(stringlist):
with open('\path\to\txt','w',encoding='utf-8') as f:
for i in range(len(stringlist)):
tmp = stringlist[i]
f.write(str(tmp)+","+"\n")
f.close()
with open('\path\to\txt','rb+',encoding='utf-8') as f:
f.seek(-3, os.SEEK_END)
f.truncate()
f.close()
大功告成!
总结
刚开始写的时候,自以为是一个很微小的环节,没想到颇花了一番力气,网上的各种方法一定要结合自身的实际业务需要对症下药、灵活变通!
参考链接:https://blog.csdn.net/qq_38060391/article/details/115969966