Python MySQLdb上传UnicodeEncodeError

时间:2015-06-14 03:20:39

标签: python mysql csv unicode utf-8

我有一个问题,我可以将CSV文件上传到MySQL,但后来发生了一些问题,我收到编码错误。可以请一些人查看我的代码并告诉我有什么问题吗?我是新来的人。

以下片段是我如何编写将要上传的CSV文件,使用MDN工具(mdb-export)从MDB文件中提取数据:

    tableIndex  = 1
    for tName in tableNames:
        fileName = os.path.join(csvPath, os.path.basename(mdb).split('.')[0] + '_' + tName + '.csv')

        try:
            p = subprocess.Popen(["mdb-export", "-H", mdb, tName], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            tableContent, error = p.communicate()

            if(p.returncode != 0):
                _logger.error('[%3d] Export Subprocess %d %s' % (tID, p.returncode, tableContent))
                SendMdbError(tID, mdb, _logger, 'ALERT: Export Subprocess')
                return(['', False])
            if(error):
                _logger.error('[%3d] Export Communicate %d %s' % (tID, p.returncode, error.strip()))
                SendMdbError(tID, mdb, _logger, 'ALERT: Export Communicate')
                return(['', False])

        except Exception as ex:
            _logger.exception('[%3d] Export Error' % tID)
            SendMdbError(tID, mdb, _logger, 'ALERT: Export Exception')
            return(['', False])
        except:
            _logger.exception('[%3d] Export Unexpected' % tID)
            SendMdbError(tID, mdb, _logger, 'ALERT: Export Unexpected')
            return(['', False])

        # If no data, no need for corresponding SQL
        if(len(tableContent) == 0):
            emptyTables.append(tName)

        # If data exists, dump data
        else:
            # Add the 'DriveTest' to the data to upload
            tableContent = tableContent.split('\n')

            tableContent = [dt + ',' + line for line in tableContent if(line)]
            tableContent = '\n'.join(tableContent)

            try:
                with open(fileName, 'wb') as f:
                    f.write(tableContent)

                    if(_VERBOSITY):
                        _logger.debug('[%3d] %3d - Write CSV SIZE[%8d] FILE: %s' %(tID, tableIndex, len(tableContent.split('\n')), fileName))
                        tableIndex += 1

            except IOError as err:
                _logger.exception('[%3d] Write IOError: %s' % (tID, str(err)))
                SendMdbError(tID, mdb, _logger, 'ALERT: Write IOError')
                return(['', False])
            except Exception as ex:
                _logger.exception('[%3d] Write Exception' % tID)
                SendMdbError(tID, mdb, _logger, 'ALERT: Write Exception')
                return(['', False])
            except:
                _logger.exception('[%3d] Write Unexpected: %s' % tID)
                SendMdbError(tID, mdb, _logger, 'ALERT: Write Unexpected')
                return(['', False])

以下是我上传CSV文件的地方,这是我收到错误的地方:

    # Upload the data
    tableIndex = 0
    for table in tableDDL:
        try:

            with warnings.catch_warnings(record=True) as war:

                _logger.info('[%3d] %3d Going up... %s' %(tID, tableIndex+1, os.path.basename(mdb).split('.')[0] + '_' + table))

                _sqlLock[tableIndex].acquire()
                #self.cursor.execute(tableDDL[table])
                self.cursor.execute(tableULD[table])
                self.conn.commit()
                _sqlLock[tableIndex].release()

                if(war):
                    #if(_VERBOSITY): print('[%3d] %3d WARNINGS[%3d] %s' % (tID, tableIndex+1, len(war), os.path.basename(mdb).split('.')[0] + '_' + table))
                    _logger.warning('[%3d] %3d WARNINGS[%3d] %s' % (tID, tableIndex+1, len(war), os.path.basename(mdb).split('.')[0] + '_' + table))
                    for w in war:
                        _logger.warning('[%3d] %s' % (tID, w.message))

                #if(_VERBOSITY): print('[%3d] %3d Uploaded %s' % (tID, tableIndex+1, os.path.basename(mdb).split('.')[0] + '_' + table))
                _logger.info('[%3d] %3d Uploaded %s' % (tID, tableIndex+1, os.path.basename(mdb).split('.')[0] + '_' + table))
                tableIndex += 1

                # Remove the uploaded CSV file
                try:
                    os.remove(csvFiles[table]+'.csv')
                    _logger.info('[%3d] Removed CVS file: %s' % (tID, csvFiles[table]+'.csv'))
                except OSError:
                    pass

        except (MySQLdb.InternalError, MySQLdb.NotSupportedError) as err:
            _logger.error('[%3d] %3d Internal: %s %s' % (tID, tableIndex+1, err, sys.exc_info()[0]))
            self.conn.rollback()
            self.Disconnect(tID, _logger, _VERBOSITY, _DEBUG)
            return(False)
        except MySQLdb.OperationalError as err:
            _logger.error('[%3d] %3d OperationalError: %s' % (tID, tableIndex+1, sys.exc_info()[0]))
            _logger.error(err)
            self.conn.rollback()
            self.Disconnect(tID, _logger, _VERBOSITY, _DEBUG)
            return(False)
        except MySQLdb.ProgrammingError as err:
            _logger.error('[%3d] %3d ProgrammingError: %s' % (tID, tableIndex+1, sys.exc_info()[0]))
            _logger.error(err)
            self.conn.rollback()
            self.Disconnect(tID, _logger, _VERBOSITY, _DEBUG)
            return(False)
        except MySQLdb.Error as err:
            _logger.error('[%3d] %3d QUERY: %s %s' % (tID, tableIndex+1, err, sys.exc_info()[0]))
            self.conn.rollback()
            self.Disconnect(tID, _logger, _VERBOSITY, _DEBUG)
            return(False)
        except Exception as err:
            _logger.error('[%3d] %3d Exception: %s %s' % (tID, tableIndex+1, err, sys.exc_info()[0]))
            #self.conn.rollback()
            #self.Disconnect(tID, _logger, _VERBOSITY, _DEBUG)
            #return(False)
            pass
        except:
            _logger.error('[%3d] %3d Other: %s' % (tID, tableIndex+1, sys.exc_info()[0]))
            self.conn.rollback()
            self.Disconnect(tID, _logger, _VERBOSITY, _DEBUG)
            return(False)

我得到的错误如下:

2015-06-13 19:42:21,743 __main__ -    ERROR - [  1]   1 Exception: 'ascii' codec can't encode character u'\xb4' in position 40: ordinal not in range(128) <type 'exceptions.UnicodeEncodeError'>
2015-06-13 19:42:30,962 __main__ -    ERROR - [  1]   1 Exception: 'ascii' codec can't encode character u'\xb4' in position 27: ordinal not in range(128) <type 'exceptions.UnicodeEncodeError'>

我注意到上传了给定的数据,但不确定是否上传了所有行。

谢谢!

3 个答案:

答案 0 :(得分:0)

在将csv放入数据库s.decode('UTF-8')并将其从数据库s.encode('UTF-8')中取出之后尝试

我是为SQLite做的,它工作正常。

答案 1 :(得分:0)

让这个工作起来不应该太困难,但你必须了解自己在做什么。不要尝试s.encode("UTF-8").decode("UTF-8")之类的所有可能组合以及类似的东西。

首先,了解stringbytes之间的区别。见https://docs.python.org/3/howto/unicode.html。您可以将字符串编码为字节:bytes = text.encode("UTF-8"),并且可以将字节解码为字符串:text = bytes.decode("UTF-8")

其次,由于CSV文件是文本文件,因此您应该以文本模式打开CSV文件。 open(fileName, 'w', encoding="utf-8")。编写文件时,无需对代码中的文本进行编码或解码。

第三,将Unicode文本写入TEXT字段是完全可以的。不需要BINARY或BLOB。但请确保您的数据库具有可以处理它的排序规则设置,通常这将是utf-8排序规则之一。然后将Unicode放入数据库中,使用python字符串,不要将它们解码为字节。

答案 2 :(得分:0)

错误消息表明MySQL中的列定义是CHARACTER SET ascii;那是对的吗?

B4听起来像´的latin1(不是utf8)编码,可能来自it´s等上下文中的Microsoft Word文档。

因此,即使将列更改为CHARACTER SET utf8也无法解决问题。

BINARYBLOB本质上是相同类型的字段 - 允许任何字节。 VARCHARTEXT验证INSERT期间的字节数,以确保它们与CHARACTER SET匹配。