Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python (长)从列表中的字符串中删除单引号_Python_Mysql_Python 3.x_Csv - Fatal编程技术网

Python (长)从列表中的字符串中删除单引号

Python (长)从列表中的字符串中删除单引号,python,mysql,python-3.x,csv,Python,Mysql,Python 3.x,Csv,这一切都有点模糊,因为该计划是相当深入的,但请坚持我,因为我会尽我所能解释它。我编写了一个程序,它接受一个.csv文件,并将其转换为MySQL数据库的INSERT-into语句。例如: ID Number Letter Decimal Random 0 1 a 1.8 A9B34 1 4 b 2.4 C8J91 2 7 c 3.7 L9O77

这一切都有点模糊,因为该计划是相当深入的,但请坚持我,因为我会尽我所能解释它。我编写了一个程序,它接受一个
.csv
文件,并将其转换为MySQL数据库的
INSERT-into
语句。例如:

ID   Number   Letter   Decimal   Random
0    1        a        1.8       A9B34
1    4        b        2.4       C8J91
2    7        c        3.7       L9O77
将导致一个insert语句,如:

插入表名('ID'int,'Number'int,'Letter'varchar()。'Decimal',float(),'Random'varchar())值('0','1','a','1.8','A9B34')

但是,并非所有
.csv
文件都具有相同的列标题,但它们需要插入到相同的表中。对于没有特定列标题的文件,我想插入一个
NULL
值来显示这一点。例如:

ID   Number   Letter   Decimal   Random
0    1        a        1.8       A9B34
1    4        b        2.4       C8J91
2    7        c        3.7       L9O77
假设第一个
.csv
文件A包含以下信息:

ID   Number   Decimal   Random
0    1        1.8       A9B34
1    4        2.4       C8J91
第二个
.csv
文件B具有不同的列标题:

ID   Number   Letter   Decimal
0    3        x        5.6
1    8        y        4.8
转换为
INSERT
语句并放入数据库后,理想情况下如下所示:

ID   TableID   Number   Decimal   Letter   Random
0    A         1        1.8       NULL     A9B34
1    A         4        2.4       NULL     C8J91
2    B         3        5.6       x        NULL
3    B         8        4.8       y        NULL
现在我可能会在这里失去你。

为了完成我需要的工作,我首先获取每个文件,并创建一个包含
.csv
文件的所有列标题的主列表:

def createMaster(path):
    global master
    master = []
    for file in os.listdir(path):
        if file.endswith('.csv'):
            with open(path + file) as inFile:
                csvFile = csv.reader(inFile)
                col = next(csvFile) # gets the first line of the file, aka the column headers
                master.extend(col) # adds the column headers from each file to the master list
                masterTemp = OrderedDict.fromkeys(master) # gets rid of duplicates while maintaining order
                masterFinal = list(masterTemp.keys()) # turns from OrderedDict to list
    return masterFinal
这将从多个
.csv
文件中获取所有列标题,并将它们按顺序组合到主列表中,无重复项:

['ID','Number','Decimal','Letter','Random']

这为我提供了
INSERT
语句的第一部分。现在,我需要将
部分添加到语句中,因此我将获取并列出每个
.csv
文件每行中的所有值,一次一个。为每行创建一个临时列表,然后将该文件的列标题列表与所有文件的列标题主列表进行比较。然后,它遍历主列表中的每一项,并尝试获取列列表中同一项的索引。如果在列列表中找到该项,则会将行列表中同一索引处的项插入临时列表中。如果找不到该项,则将其插入临时列表中。完成临时列表后,它将以正确的MySQL语法将列表转换为字符串,并将其附加到
.sql
文件中进行插入。以下是代码中的相同想法:

def createInsert(inPath, outPath):
    for file in os.listdir(inpath):
        if file.endswith('.csv'):
            with open(inPath + file) as inFile:
                with open(outPath + 'table_name' + '.sql', 'a') as outFile:
                    csvFile = csv.reader(inFile)
                    col = next(csvFile) # gets the first row of column headers
                    for row in csvFile:
                        tempMaster = [] # creates a tempMaster list
                        insert = 'INSERT INTO ' + 'table_name' + ' (' + ','.join(master)+ ') VALUES ' # SQL syntax crap
                        for x in master:
                            try:
                                i = col.index(x) # looks for the value in the column list
                                r = row[i] # gets the row value at the same index as the found column
                                tempMaster.append(r) # appends the row value to a temporary list
                            except ValueError:
                                tempMaster.append('NULL') # if the value is not found in the column list it just appends the string to the row master list
                            values = map((lambda x: "'" + x.strip() + "'"), tempMaster) # converts tempMaster from a list to a string
                            printOut = insert + ' (' + ','.join(values) + '):')
                            outFile.write(printOut + '\n') # writes the insert statement to the file
现在终于开始提问了。

此程序的问题在于
createInsert()
从tempMaster列表中获取所有行值,并通过以下行将它们与
标记联接:

values = map((lambda x: "'" + x.strip() + "'"), tempMaster)
这一切都很好,只是MySQL希望插入
NULL
值,只插入
NULL
而不是
'NULL'

如何获取集合行列表并搜索
'NULL'
字符串并将其更改为
NULL

我有两个不同的想法:

我可以沿着这些思路做一些事情,从
标记中提取
NULL
字符串,并将其替换到列表中

def findBetween(s, first, last):
    try:
        start = s.index(first) + len(first)
        end = s.index(last, start)
        return s[start:end]
    except ValueError:
        print('ERROR: findBetween function failure.')

def removeNull(aList):
    tempList = []
    for x in aList:
        if x == 'NULL':
            norm = findBetween(x, "'", "'")
            tempList.append(norm)
        else:
            tempList.append(x)
    return tempList
或者我可以将
NULL
值添加到列表中,而不首先添加
。这在
createInsert()函数中

但是,我认为这两种方法都不可行,因为它们会显著降低程序的速度(因为文件越大,会产生
内存错误
)。因此,我在征求你的意见。如果这令人困惑或难以理解,我深表歉意。请让我知道我可以解决什么,使它更容易理解,如果是这样的情况下,并祝贺它的结束

而不是

values = map((lambda x: "'" + x.strip() + "'"), tempMaster)
把这个

 values = map((lambda x: "'" + x.strip() + "'" if x!='NULL' else x), tempMaster)
编辑 感谢您接受/支持我的简单技巧,但我不确定这是否最佳。 在更全局的范围内,您可以避免这个map/lambda的东西(除非我遗漏了什么)


然后您就可以正确填充
值,节省内存和CPU。

我检查了您的要求,发现您的目录中有多个CSV。这些csv具有动态列。我的方法是创建所有列的静态列表

staticColumnList=[“ID”、“TableID”、“Number”、“Decimal”、“Letter”、“Random”]

现在,当读取文件时,获取标题行并为对应列的元组创建临时列表,如

[(csv中的ID、列号),(表格ID、“A”-文件名),(csv中的编号、列号)等]

若csv中并没有列,那个么将x放入类似
(“字母”,x)
的对应关系中。现在,对每一行进行循环,并按如下方式分配或拾取值:-

wholeDataList = []
rowList = []
for column in staticColumnList:
    if int of type(column[1]):
      rowList.append("'"+str(rowCSV[column[1]])+"'")
    elif 'X' == column[1]:
      rowList.append('null')
    else:
      rowList.append("'"+column[1]+"'")


wholeDataList.append("("+",".join(rowList)+")")
qry = "INSERT into .. ("+",".join(staticColumnList)+") values " + ",".join(wholeDataList)
最后你有了准备充分的陈述,比如:-

wholeDataList = []
rowList = []
for column in staticColumnList:
    if int of type(column[1]):
      rowList.append("'"+str(rowCSV[column[1]])+"'")
    elif 'X' == column[1]:
      rowList.append('null')
    else:
      rowList.append("'"+column[1]+"'")


wholeDataList.append("("+",".join(rowList)+")")
qry = "INSERT into .. ("+",".join(staticColumnList)+") values " + ",".join(wholeDataList)

你真的试过他们看他们有多慢吗?是的,我试过。它可以运行一些较小的
.csv
文件,但在对一些较大的文件执行时会生成一个
MemoryError
。告诉我,如果这是在以下列中的一列中:
“DROP TABLE_name;”
?这种插入数据的方法容易受到SQL注入攻击。决不能向SQL查询添加任意输入。你应该考虑使用类似SQLAlchemy的东西来帮助你隔离。@I如果我决定进一步实施这个程序,这肯定是下一步。然而,目前这只是作为一种临时方法,将旧数据(我知道是安全的)插入到新的数据库中。我将研究您的评论以及SQLAlchemy,以帮助避免将来出现这些潜在问题。谢谢你的建议!我在问题中没有提到的部分程序中犯了一个错误,但一旦我修复了它,它就完美地工作了。谢谢检查我的上一次编辑,也许我们可以做得更好、更简单(好吧,我们不会使用
map
lambda
,这看起来不那么令人印象深刻,这是缺点:)