[英]Python 3 UnboundLocalError: local variable referenced before assignment in try statement
I'm trying to make a program that handles RSA encryption and decryption for sending messages using the rsa library.我正在尝试制作一个程序来处理 RSA 加密和解密,以便使用 rsa 库发送消息。 Currently I'm implementing it to use only 1 key pair, but it'll be changed later on.目前我正在实施它以仅使用 1 个密钥对,但稍后会更改。 I'm having some trouble with the logic to check whether the files that store the keys exist or not.我在检查存储密钥的文件是否存在的逻辑上遇到了一些问题。 The logic for these functions looks like so:这些函数的逻辑如下所示:
import rsa
################################################
keySize = 256
################################################
def genKeys():
pubkey, privkey = rsa.newkeys(keySize)
with open("public.pem", "w") as pub:
pub.write(str(pubkey))
with open("private.pem", "w") as priv:
priv.write(str(privkey))
return pubkey, privkey
def readKeys():
with open("private.pem", "r") as priv:
keydata = priv.read()
privkey = rsa.PrivateKey.load_pkcs1(keydata)
print(privkey)
with open("public.pem", "r") as pub:
keydata = pub.read()
pubkey = rsa.PublicKey.load_pkcs1(keydata)
print(pubkey)
return pubkey, privkey
def send(message, pubkey):
message = message.encode('utf-8')
crypto = rsa.encrypt(message, pubkey)
return crypto
def recv(crypto, privkey):
message = rsa.decrypt(crypto, privkey)
message = message.decode('utf-8')
return message
def main():
global pubkey, privkey
try:
if (open("private.pem", "r") and open("public.pem", "r")) == True:
pubkey, privkey = readKeys()
except:
(pubkey, privkey) = genKeys()
cryptMessage = send('hello world', pubkey)
print(cryptMessage)
print(recv(cryptMessage, privkey))
if __name__ == "__main__":
main()
The main()
function, specifically the try: except:
statement is where my problem resides. main()
function,特别是try: except:
语句是我的问题所在。 The error I'm getting is builtins.NameError: name 'pubkey' is not defined
.我得到的错误是builtins.NameError: name 'pubkey' is not defined
。 I've tried declaring the variables as global, which is what other answers suggested, but that didn't work for me, or I'm doing it wrong.我尝试将变量声明为全局变量,这是其他答案所建议的,但这对我不起作用,或者我做错了。
Thanks for the help.谢谢您的帮助。 Sorry for the noob question.对不起菜鸟问题。
EDIT: So, that solved my first problem.编辑:所以,这解决了我的第一个问题。 However, now when I use the try/except
statement, it tries to call the variables, which have a value of None
, even though I'm assigning them a value using the functions.但是,现在当我使用try/except
语句时,它会尝试调用值为None
的变量,即使我使用函数为它们分配了值。 The stack trace is堆栈跟踪是
File "", line 61, in <module>
main()
File "", line 56, in main
cryptMessage = send('hello world', pubkey)
File "", line 37, in send
crypto = rsa.encrypt(message, pubkey)
File "/usr/local/lib/python3.6/dist-packages/rsa/pkcs1.py", line 169, in encrypt
keylength = common.byte_size(pub_key.n)
builtins.AttributeError: 'NoneType' object has no attribute 'n'
Even if you declare a variable as global inside a function, you still need to initialize it, or in the global scope or while declaring them. 即使您将变量声明为函数内部的全局变量,仍然需要在全局范围内或在声明变量时对其进行初始化。
import rsa
################################################
keySize = 256
################################################
# DECLARATION IN GLOBAL SCOPE
pubkey = None
privkey = None
def genKeys():
pubkey, privkey = rsa.newkeys(keySize)
with open("public.pem", "w") as pub:
pub.write(str(pubkey))
with open("private.pem", "w") as priv:
priv.write(str(privkey))
return pubkey, privkey
def readKeys():
with open("private.pem", "r") as priv:
keydata = priv.read()
privkey = rsa.PrivateKey.load_pkcs1(keydata)
print(privkey)
with open("public.pem", "r") as pub:
keydata = pub.read()
pubkey = rsa.PublicKey.load_pkcs1(keydata)
print(pubkey)
return pubkey, privkey
def send(message, pubkey):
message = message.encode('utf-8')
crypto = rsa.encrypt(message, pubkey)
return crypto
def recv(crypto, privkey):
message = rsa.decrypt(crypto, privkey)
message = message.decode('utf-8')
return message
def main():
# DECLARATION INSIDE THE FUNCTION
global pubkey, privkey; pubkey = privkey = None
try:
if (open("private.pem", "r") and open("public.pem", "r")) == True:
pubkey, privkey = readKeys()
except:
(pubkey, privkey) = genKeys()
cryptMessage = send('hello world', pubkey)
print(cryptMessage)
print(recv(cryptMessage, privkey))
if __name__ == "__main__":
main()
You should declare the variables pubkey and privkey outside the function genKeys()
and then the error should vanish. 您应该在genKeys()
函数外部声明变量pubkey和privkey,然后错误应消失。 This is my first post, I hope to be helpful. 这是我的第一篇文章,希望对您有所帮助。 Regards. 问候。
Your problem is here: 您的问题在这里:
if (open("private.pem", "r") and open("public.pem", "r")) == True:
Python logical operators return the last inspected value, not True or False. Python逻辑运算符返回最后检查的值,而不是True或False。 That value was a file
object from the open command is not equal to True. 该值是来自open命令的file
对象,不等于True。 You could check the files for existence with os.path.isfile
and skip the try/except block completely. 您可以使用os.path.isfile
检查文件是否存在,并完全跳过try / except块。 Or you could just try the actual read the in the try block, like so 或者您可以尝试在try块中实际读取,就像这样
(slimmed down for demo) (为演示而精简)
# dummys for test...
def readKeys():
print('try read')
return open('public.pem').read(), open('private.pem').read()
def genKeys():
print('try write')
open('public.pem','w').write('foo')
open('private.pem','w').write('bar')
return 'foo', 'bar'
def main():
global pubkey, privkey
try:
pubkey, privkey = readKeys()
except:
(pubkey, privkey) = genKeys()
if __name__ == "__main__":
main()
Copying the code of the other answer and with the change to check for globals()
instead of overwriting None
variables at every function call.复制另一个答案的代码并进行更改以检查globals()
而不是在每次 function 调用时覆盖None
变量。
import rsa
################################################
keySize = 256
################################################
# DECLARATION IN GLOBAL SCOPE
pubkey = None
privkey = None
def genKeys():
pubkey, privkey = rsa.newkeys(keySize)
with open("public.pem", "w") as pub:
pub.write(str(pubkey))
with open("private.pem", "w") as priv:
priv.write(str(privkey))
return pubkey, privkey
def readKeys():
with open("private.pem", "r") as priv:
keydata = priv.read()
privkey = rsa.PrivateKey.load_pkcs1(keydata)
print(privkey)
with open("public.pem", "r") as pub:
keydata = pub.read()
pubkey = rsa.PublicKey.load_pkcs1(keydata)
print(pubkey)
return pubkey, privkey
def send(message, pubkey):
message = message.encode('utf-8')
crypto = rsa.encrypt(message, pubkey)
return crypto
def recv(crypto, privkey):
message = rsa.decrypt(crypto, privkey)
message = message.decode('utf-8')
return message
def main():
# DECLARATION INSIDE THE FUNCTION
global pubkey, privkey;
if 'pubkey' not in globals() or 'privkey' not in in globals():
pubkey = privkey = None
try:
if (open("private.pem", "r") and open("public.pem", "r")) == True:
if 'pubkey' in globals() and 'privkey' in globals():
pubkey, privkey = readKeys()
except:
if 'pubkey' in globals() and 'privkey' in globals():
(pubkey, privkey) = genKeys()
if 'pubkey' in globals() and 'privkey' in globals():
cryptMessage = send('hello world', pubkey)
print(cryptMessage)
print(recv(cryptMessage, privkey))
if __name__ == "__main__":
main()
This is untested.这是未经测试的。 I did that for local variables instead where a local connection object was closed in the finally block.我对局部变量执行此操作,而不是在 finally 块中关闭了本地连接 object。 For that, I did not even have to set the objects as None
at any time since I checked for the connection object to be in globals()
before closing it.为此,我什至不必在任何时候将对象设置为None
,因为我在关闭它之前检查了连接 object 是否在globals()
中。 The error was gone.错误消失了。
In this code, however, you do not just close objects, you overwrite them instead, both in the try
and in the except
block.然而,在这段代码中,您不仅关闭了对象,还覆盖了它们,无论是在try
块中还是在except
块中。 Therefore, I just guess that you need to make the None
objects at first loading time.因此,我只是猜测您需要在第一次加载时创建None
对象。 If this trick works for global variables as well, this will be the only code that does not overwrite global objects with None
every time the function gets called, but only if the variables are touched the first time.如果这个技巧也适用于全局变量,那么这将是唯一不会在每次调用 function 时用None
覆盖全局对象的代码,但前提是第一次接触到变量。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.