Reputation: 227
I would like to backup database using Python code. I want to backup some tables of related data. How to backup and how to choose desired tables using "SELECT" statement?
e.g.
I want to get data from 2014-05-01 to 2014-05-10 of some tables and output this result as .sql extension file
How can I get this format using python code? If you don't mind, please explain. Thanks.
Upvotes: 17
Views: 36092
Reputation: 1
Upvotes: 0
Reputation: 1701
Use psycopg2 to establish the data connection. There are quite a few examples in the documentation:
Once you have your data source configured, iterate through the results of your "SELECT" statement building a INSERT INTO
statement by printing the result set to a file. Basically some reverse logic.
That way, if the time comes and you need to use your backup file, you simply run the SQL file which inserts the data back in...
Example:
import psycopg2
import sys
con = None
try:
con = psycopg2.connect(database='local', user='local', password='local',port='1970')
cur = con.cursor()
cur.execute('SELECT x FROM t')
f = open('test.sql', 'w')
for row in cur:
f.write("insert into t values (" + str(row) + ");")
except psycopg2.DatabaseError, e:
print 'Error %s' % e
sys.exit(1)
finally:
if con:
con.close()
Then to restore:
psql <dbname> <username> < test.sql
Upvotes: 14
Reputation: 928
If your OS is Linux, you can use the code below.
First, you should run apt-get install postgresql
.
def create_essentials():
yaml_file = open("settings.yaml", 'r')
settings = yaml.load(yaml_file)
db_name = settings["db_name"]
db_user = settings["db_user"]
db_password = settings["db_password"]
db_host = settings["db_host"]
db_port = settings["db_port"]
backup_path = settings["backup_path"]
filename = settings["filename"]
filename = filename + "-" + time.strftime("%Y%m%d") + ".backup"
command_str = str(db_host)+" -p "+str(db_port)+" -d "+db_name+" -U "+db_user
return command_str, backup_path, filename
def backup_database(table_names=None):
command_str,backup_path,filename = create_essentials()
command_str = "pg_dump -h "+command_str
if table_names is not None:
for x in table_names:
command_str = command_str +" -t "+x
command_str = command_str + " -F c -b -v -f '"+backup_path+"/"+filename+"'"
try:
os.system(command_str)
print "Backup completed"
except Exception as e:
print "!!Problem occured!!"
print e
def restore_database(table_names=None):
command_str,backup_path,filename = create_essentials()
command_str = "pg_restore -h "+command_str
if table_names is not None:
for x in table_names:
command_str = command_str +" -t "+x
command_str = command_str + " -v '"+backup_path+"/"+filename+"'"
try:
os.system(command_str)
print "Restore completed"
except Exception as e:
print "!!Problem occured!!"
print e
Upvotes: 4
Reputation: 5048
The first idea that comes to my mind is to dump your tables calling pg_dump command, similar to the approach presented here (but google is plenty of alternatives).
However, since your backup strategy requires you to select precise dates and not only tables, you will probably have to rely on a sequence of queries, and then my advise is to use a library like Psycopg.
EDIT:
I cannot provide a complete example since I don't know:
the following example generates a file that stores the result of a single query.
import psycopg
conn = psycopg2.connect("dbname=test user=postgres") # change this according to your RDBMS configuration
cursor = conn.cursor()
table_name='YOUR_TABLE_HERE' # place your table name here
with open("table_dump.sql") as f:
cursor.execute("SELECT * FROM %s" % (table_name)) # change the query according to your needs
column_names = []
columns_descr = cursor.description
for c in columns_descr:
column_names.append(c[0])
insert_prefix = 'INSERT INTO %s (%s) VALUES ' % (table_name, ', '.join(column_names))
rows = cursor.fetchall()
for row in rows:
row_data = []
for rd in row:
if rd is None:
row_data.append('NULL')
elif isinstance(rd, datetime.datetime):
row_data.append("'%s'" % (rd.strftime('%Y-%m-%d %H:%M:%S') ))
else:
row_data.append(repr(rd))
f.write('%s (%s);\n' % (insert_prefix, ', '.join(row_data))) # this is the text that will be put in the SQL file. You can change it if you wish.
Upvotes: 1