Python在传递Try-Except块后引发错误



我正在使用这个脚本在PostgreSQL中创建一个数据库和一个用户"集群";然后创建存在于另一个模式中的新模式(我只是复制它们的名称(。

我使用的是Python 2.7.5,下面是我的脚本:

import sys
import psycopg2
import getpass
def connect_db(database):
connection = psycopg2.connect(user="postgres",
password="mypass",
host="127.0.0.1",
port="5432",
database=str(database))
connection.autocommit = True
cursor = connection.cursor()
return cursor

def execute_query_2_select(cursor, query):
try:
cursor.execute(query)
output = cursor.fetchall()
return output
except Exception as e:
print(e)

def execute_query_2_create(cursor, query):
try:
cursor.execute(query)
except Exception as e:
print(e)

def main():
source_database = str(raw_input("Enter a tns name(DB_UNIQUE_NAME): ")).strip()
target_database = str(raw_input("Enter a username(OID): ")).strip()
user_password = str(getpass.getpass("Enter the password of" )).strip()
try:
cursor_source = connect_db(source_database)
except Exception:
print("Please check your input and try again.n")
main()
query_2_get_schemas = "select schema_name from information_schema.schemata where schema_name not like 'pg_%' and schema_name not in ('public', 'information_schema');"
schema_template_list = execute_query_2_select(cursor_source, query_2_get_schemas)
cursor_source.close()
cursor_postgres = connect_db("postgres")
execute_query_2_create(cursor_postgres, "create user {x} with encrypted password '{y}';".format(x=target_database, y=user_password))
execute_query_2_create(cursor_postgres, "create database {x} owner {x};".format(x=target_database))
cursor_postgres.close()
cursor_target = connect_db(target_database)
for i in schema_template_list:
execute_query_2_create(cursor_target, "CREATE SCHEMA IF NOT EXISTS {x};".format(x=i[0]))
execute_query_2_create(cursor_target, "GRANT USAGE ON SCHEMA {x} TO {x};".format(x=i[0]))
execute_query_2_create(cursor_target, "GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA {x} TO {x};".format(x=i[0]))
execute_query_2_create(cursor_target, "GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA {x} to {x};".format(x=i[0]))
execute_query_2_create(cursor_target, "ALTER DEFAULT PRIVILEGES IN SCHEMA {x} GRANT ALL PRIVILEGES ON TABLES TO {x};".format( x=i[0]))
execute_query_2_create(cursor_target, "ALTER DEFAULT PRIVILEGES IN SCHEMA {x} GRANT ALL PRIVILEGES ON SEQUENCES TO {x};".format( x=i[0]))
execute_query_2_create(cursor_target, "ALTER SCHEMA {x} OWNER TO {x};".format(x=i[0]))
print("Commands for schema {x} are executed!".format(x=i[0]))
cursor_target.close()
if __name__ == "__main__":
main()

由于异常阻止

except Exception:
print("Please check your input and try again.n")
main()

如果用户提供了错误的连接数据,我会让他们返回并检查他们的输入,然后再次输入。为了在第一次尝试时测试脚本,我提供了不正确的连接数据。然后它又回到了我想要的地方。最后,我提供了正确的信息,但这次我得到了"UnboundLocalError:在赋值之前引用了局部变量"cursor_source";。为什么?它在第二次/以后的尝试中定义。

输出:

Enter a database name for schema pattern: asdaslkdjals
Enter a database/user name to create: asdasd
Enter the password of user asdasd
Please check your input and try again.
Enter a database name for schema pattern: test_source
Enter a database/user name to create: test_target
Enter the password of user test_target
Commands for schema test_schemaxx are executed!
Traceback (most recent call last):
File "schema.py", line 68, in <module>
main()
File "schema.py", line 44, in main
schema_template_list = execute_query_2_select(cursor_source, query_2_get_schemas)
UnboundLocalError: local variable 'cursor_source' referenced before assignment

这是递归程序的流程,示例如下:首先是错误的输入,然后是好的输入:

  1. 您呼叫main
  2. try中传递错误输入
  3. 执行except并再次调用main
    1. 您传递了良好的输入
    2. try执行起来没有问题
    3. 函数的其余部分运行并返回
  4. 递归调用结束-返回到第一个调用
  5. 现在,第一个main在没有定义cursor_source的情况下继续运行(因为try失败(

您需要的基本上是将except之后的所有代码放在else块中——如果没有错误,这就是您想要运行的。但在这种情况下,简单地return会更容易:

try:
cursor_source = connect_db(source_database)
except Exception:
print("Please check your input and try again.n")
main()
return

但避免递归并简单地使用循环会更容易:

while True:
source_database = str(raw_input("Enter a tns name(DB_UNIQUE_NAME): ")).strip()
target_database = str(raw_input("Enter a username(OID): ")).strip()
user_password = str(getpass.getpass("Enter the password of" )).strip()
try:
cursor_source = connect_db(source_database)
except Exception:
print("Please check your input and try again.n")
else:
break

# rest of function

您尝试过全局语句吗?将全局置于循环中,例如:

A = 20
def main():
print(‘Does Something’)
input = input(‘ variable a’s new value : ‘)
#input == 10
main()

如果您试图访问函数内部的变量,它将给出错误。但如果你这样做:

A = 20
def main():
global A
print(‘Does Something’)
input = input(‘ variable A’s new value : ‘)
#input == 10
main()

这将停止出现错误。

我不是100%理解为什么要获得未绑定的本地,但从异常处理程序调用main绝对是个坏主意。

根据用户必须重试的次数,您可以进入无限递归,可能会留下各种半初始化的连接。

相反,您应该在while循环中重试,这样您就不必退出主函数。

最新更新