首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在文件中写入150万行

在文件中写入150万行
EN

Code Review用户
提问于 2019-08-29 22:26:53
回答 2查看 1.1K关注 0票数 6

我正在生成( MySQL格式的) SQL语句,并将其写入文件以创建10,000个表。每个表包含5个列,每个列中有150万行数据。我使用regex和faker模块生成了这些数据。因此,我有一个10,000的循环(每个create表都有一个语句),在这个循环中,我有一个150万的循环(将插入数据行到创建的每个表中)。

代码运行正常,但extremely运行缓慢。有什么办法能让这个动作跑得更快吗?

代码语言:javascript
复制
import rstr
import random
from faker import Faker
import time

fake = Faker()

name = ['Name', 'Person_Name', 'Customer_Name', 'Employee_Name', 'Contact_Name', 'CustName', 'EmpName']
ssn = ['SSN', 'Social_Security_Number', 'National_Identification_Number', 'NID', 'US_SSN', 'Social_Number', 'Social_Security_No', 'Social_Security_Num', 'Customer_Social_Security Number', 'Employee_Social_Security_Number']
address = ['Address', 'Customer_Location_Details', 'Employee_Address_Details', 'Address_Det.', 'Add_Line_1', 'Add_Line_2', 'Address_Line_1', 'Address_Line_2']
dob = ['DOB', 'Date_Of_Birth', 'Birth_Date', 'V_VLD_BRTH_DT', 'DAY_OF_BRTH', 'DT_OF_BIRTH']
phone = ['Phone_Number', 'Contact_Number', 'Office_Phone', 'Residential_phone', 'Contact_Phone']

ssn1='(?!000|.+0{4})(?:\d{9})'
ssn2='(?!000|.+0{4})(\d{3}-\d{2}-\d{4})'
sList=[ssn1,ssn2]

db1='^(0[1-9]|[12][0-9]|3[01])[/](0[1-9]|1[012])[/](19)\d\d
db2='^(19)\d\d$[.](0[1-9]|1[012])[.](0[1-9]|[12][0-9]|3[01])'
db3='^(19)\d\d$[-](0[1-9]|1[012])[-](0[1-9]|[12][0-9]|3[01])'            
db4='^(0[1-9]|[12][0-9]|3[01])[-](0[1-9]|1[012])[-](19)\d\d
db5='^(0[1-9]|[12][0-9]|3[01])[.](0[1-9]|1[012])[.]\d\d
dbList=[db1,db2, db3, db4, db5]

p1='1[2-9][0-8][0-9][2-9][0-9]{2}[0-9]{4}'
p2='[2-9][0-8][0-9][2-9][0-9]{2}[0-9]{4}'
p3='001[2-9][0-8][0-9][2-9][0-9]{2}[0-9]{4}'
p4='[(][\d]{3}[)][ ]?[\d]{3}-[\d]{4}'
p5='\+1[2-9][0-8][0-9][2-9][0-9]{2}[0-9]{4}'
p6='(\d{3}\d{3}\d{4})'
p7='[2-9][0-8][0-9][-][2-9][0-9]{2}[-][0-9]{4}'
pList=[p1, p2, p3, p4, p5, p6, p7]

tables=10001
rows=1500001

with open("D:\Output.sql", "a") as text_file:
    count = 0

    for i in range(1,tables):
        a=[]
        b=[]
        j=str(i)
        x=f'Tab_{i}'

        #a.append(random.choice(name)+'_'+j)
        #a.append(random.choice(ssn)+'_'+j)
        #a.append(random.choice(address)+'_'+j)
        #a.append(random.choice(dob)+'_'+j)
        #a.append(random.choice(phone)+'_'+j)
        a.extend(f'{random.choice(n)}_{j}' for n in (name, ssn, address, dob, phone))

        text_file.write(f"create table Python_test.{x}({a[0]} VARCHAR(255),{a[1]} VARCHAR(255),{a[2]} VARCHAR(255),{a[3]} VARCHAR(255),{a[4]} VARCHAR(255));\n")

        start = time.time()
        for j in range(1,rows):
            text_file.write(f"insert into {x}({a[0]},{a[1]},{a[2]},{a[3]},{a[4]}) values ('{fake.name()}','{rstr.xeger(random.choice(sList))}','{fake.address()}','{rstr.xeger(random.choice(dbList))}','{rstr.xeger(random.choice(pList))}');\n")

        print(time.time() - start) 
        text_file.write('\n')
        count+=1
        print(count)
EN

回答 2

Code Review用户

发布于 2019-08-30 00:54:38

with

中使用open

...so,无论是否存在任何可能的异常,都可以保证您的文件关闭。

使用f-string

所以这样的事情:

代码语言:javascript
复制
x='Tab_'+str(i)

转成

代码语言:javascript
复制
x = f'Tab_{i}'

计算机擅长重复

代码语言:javascript
复制
a.append(random.choice(name)+'_'+str(i))
a.append(random.choice(ssn)+'_'+str(i))
a.append(random.choice(address)+'_'+str(i))
a.append(random.choice(dob)+'_'+str(i))
a.append(random.choice(phone)+'_'+str(i))

可以是

代码语言:javascript
复制
a.extend(f'{random.choice(n)}_{i}' for n in (name, ssn, address, dob, phone))

注入攻击

除非您对数据的来源、安全性和有效性很有信心,否则构建一个字符串并将其作为可执行SQL发送是数据库安全性的敌人之一。这就是准备好的陈述的意义所在。目前还不清楚您需要什么样的SQL,因此也不清楚您需要哪一个库。

组合赋值/增量

代码语言:javascript
复制
count=count+1

可以是

代码语言:javascript
复制
count += 1
票数 11
EN

Code Review用户

发布于 2019-08-30 01:13:47

文档字符串

您应该在编写的每个模块、类和函数的开头包含一个docstring。这将使文档能够识别您的代码应该做什么。

with openfile = open

目前,您使用text_file = open("D:\Output.sql", "a", encoding="utf-8")打开文件,并使用text_file.close()手动关闭它。您可以通过使用with open(...) as ...:打开文件来避免这样做。这使您可以使用该文件,并且一旦完成并超出范围,就可以继续编写程序。“但是等等,关闭文件怎么样?”当您使用with时,一旦您超出了with的范围,它就会自动关闭。

幻数

代码语言:javascript
复制
for i in range(1,10001): ...
for j in range(1,1500001): ...

乍一看,我不知道这些数字应该代表什么。您应该将这些数字分配给变量,并使用这些变量。这使得代码更简洁,更易于维护。如果您想更改表的数量或人数,该怎么办?您需要找到这个神奇数字的每个实例(如果您不止一次使用它)并更改它。将它分配给变量可以解决这个问题,因为您只需更改变量的值即可。

字符串格式化f""

text_file.write('create table Python_test.'+x+'('+a[0]+' VARCHAR(255),'+a[1]+' VARCHAR(255),'+a[2]+' VARCHAR(255),'+a[3]+' VARCHAR(255),'+a[4]+' VARCHAR(255));\n')

这读起来很痛。所有的+都将字符串分开,因此很难知道整个字符串是什么。我的解决方案是使用f"..."。这允许您直接将变量合并到字符串中,而不必使用+...+,也可以避免(如果存在) +str(...)+,这对我来说非常难看。

对象

有一个重新定义的列表与固定位置的人的属性是混乱的。相反,您可以生成一个包含Person实例的列表,并且可以在将其合并到SQL字符串中时访问它们的属性。

用于未使用循环变量的

_

在循环中不使用变量时,例如:

代码语言:javascript
复制
for i in range(5):
    print("Hi!")

您应该使用_。这清楚地表明,不需要用于循环的变量,应该忽略它。

帮助函数

我编写了一些帮助函数,用于在代码中生成一些随机值。在代码中使用助手函数确实可以帮助您,因为您不必将所有内容都塞进一个函数中。

免责声明:我不知道您在向表中插入数据时要做什么,所以我留下了空白。fakerstr没有定义/没有显示在您的程序中也没有帮助。

Updated代码

代码语言:javascript
复制
"""
Module Docstring
A description of your program goes here
"""

import random

class Person():
    """
    Class to store properties of Person
    """

    def __init__(self, name, ssn, address, dob, phone):
        self.name = name
        self.ssn = ssn
        self.address = address
        self.dob = dob
        self.phone = phone

def generate_ssn():
    """
    Returns a randomly generated SSN
    """
    return f"{random.randint(100, 999)}-{random.randint(10, 99)}-{random.randint(1000, 9999)}"

def generate_dob():
    """
    Returns a randomly generated address in format MM/DD/YYYY
    """
    return f"{random.randint(1, 12)}/{random.randint(1, 31)}/{random.randint(1919, 2019)}"

def generate_phone():
    """
    Returns a randomly generated phone number
    """
    return f"{random.randint(100, 999)}-{random.randint(100, 999)}-{random.randint(1000, 9999)}"

def generate_sql_script(num_people, num_tables, output_file):
    """
    Generates an SQL script for inserting people into tables
    """
    with open(output_file, "a") as out_file:
        people = []
        count = 0
        for i in range(1, num_people):
            people.append(Person(f"John_{i}",
                                 generate_ssn(),
                                 f"123 Main St_{i}",
                                 generate_dob(),
                                 generate_phone())
                         )
            random_person = random.choice(people)
            table = f"Tab_{i}"
            out_file.write(f'CREATE TABLE Python_test.{table}({random_person.name} VARCHAR(255), {random_person.ssn} VARCHAR(255), {random_person.address} VARCHAR(255), {random_person.dob} VARCHAR(255), {random_person.phone} VARCHAR(255)')

            for _ in range(1, num_tables):
                #Couldn't understand what this is doing with `fake` and `rstr`
                pass

            out_file.write('\n')
            count += 1
            print(count)
票数 6
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/227129

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档