我目前正在从多个SQL Server数据库到AWS Redshift进行大规模数据迁移。我正在使用python + bonobos-etl来完成此任务,到目前为止,我对此感到非常满意。但是,在迁移一个特定的表时,我遇到了一个问题,即有特定字符无法转移到Redshift中。 Redshift错误如下:
Missing newline: Unexpected character 0x20 found at location 226
据我了解(尽管我可能错了),这是EOL字符的ASCII编码。
即使我删除有问题的行,有时也会在导入的数百万行中偶尔发现此错误,因此我想在数据提取期间解决此问题。
有问题的字符在我的.csvs中显示为:
�
当我在SQL Server管理器中查看它时,根本没有出现。
这是我的数据清理功能(一定有点混乱):
def transform(row, **kwargs):
"""Placeholder, change, rename, remove... """
global commitCounter
print(commitCounter)
commitCounter += 1
for myDict in row:
for k,v in myDict.items():
myDict[str(k)] = re.sub(' +', ' ', str(v)).strip()
if myDict[str(k)] == "None":
myDict[str(k)] = None
try: myDict[str(k)] = re.sub('<[^>]*>', '', myDict[str(k)]).replace("\n", "").replace("\t", "").replace("\r", "").replace("|", "")
except: pass
try:
myDict[str(k)] = re.sub(r'[^\x00-\x7F]+',' ', myDict[str(k)])
except: pass
try:
datetime.datetime.strptime(myDict[str(k)],'%Y-%m-%d %H:%M:%S.%f')
myDict[str(k)] = myDict[str(k)].rpartition('.')[0]
except: pass
yield myDict
给我的印象是,代码中的这一行专门处理了该问题:
myDict[str(k)] = re.sub(r'[^\x00-\x7F]+',' ', myDict[str(k)])
但是显然不是。我无法使用正则表达式解决此问题,因为我无法将字符复制/粘贴到python shell或正则表达式测试服务中。有什么快速简便的方法可以检查我的麻烦人物吗?谢谢。
答案 0 :(得分:0)
所以我相信我已经弄清楚了我的问题。尽管AWS Redshift将问题报告为Missing newline: Unexpected character 0x20 found at location 226
,但是在将字符串转换为字节字符串后,我发现错误编码的字符串的实际值为:x00
。现在可以理解为什么myDict[str(k)] = re.sub(r'[^\x00-\x7F]+',' ', myDict[str(k)])
不能正确过滤掉字符,因为\x00
在可接受的范围内。我改为添加了另一个try / except块,现在我在其中用空字符串替换\x00
,例如:myDict[str(k)] = re.sub('\x00', '', myDict[str(k)])
我的.csvs现在没有替换字符,因此我认为问题已解决。奇怪的是,AWS在实际0x20
中将字符报告为x00
,但是我不确定这是否是它们的错误,或者我是否误解了字符编码。谢谢所有提出建议的人,因为我只能通过您的指导来解决。我知道回答我自己的问题有点古怪,因此,如果这违反了StackOverflow准则,请随时结束此问题。谢谢。