TypeError:无法将“ Entry”对象隐式转换为str

时间:2019-07-07 15:20:19

标签: python encryption

我正在尝试制作一个简单的应用程序来加密文本。我不知道怎么了。

起初它确实可以运行,但是当按下“加密”按钮时,会提示错误,提示未定义密钥和文件名。

#!/usr/bin/python

import os
from Crypto.Cipher import AES
from Crypto.Hash import SHA256
from Crypto import Random
from appJar import gui
import datetime
import csv

def encrypt(key, filename):
    chunksize = 64*1024
    outputFile = "(encrypted)"+filename
    filesize = str(os.path.getsize(filename)).zfill(16)
    IV = Random.new().read(16)

    encryptor = AES.new(key, AES.MODE_CBC, IV)

    with open(filename, 'rb') as infile:
        with open(outputFile, 'wb') as outfile:
            outfile.write(filesize.encode('utf-8'))
            outfile.write(IV)

            while True:
                chunk = infile.read(chunksize)

                if len(chunk) == 0:
                    break
                elif len(chunk) % 16 != 0:
                    chunk += b' ' * (16 - (len(chunk) % 16))

                outfile.write(encryptor.encrypt(chunk))

with gui('Encryption App', '400x200', font={'size':18}) as app:
    app.label('Simple encryption app')
    app.entry('Type text to encrypt: ', label=True, focus=True)
    filename = app.entry('Save as: ',label=True)
    key = app.entry("Password", label=True, secret=True)
    app.buttons(['Encrypt', 'Cancel'], [encrypt(app.entry('Save as: '),app.entry('Password: ')), app.stop])

运行时,显示错误消息:

2019-07-07 17:40:44,862 appJar:ERROR [Line 40->1784/__exit__]: ContextManager failed: Can't convert 'Entry' object to str implicitly
Traceback (most recent call last):
  File "/home/skyandstars/Desktop/new_score.py", line 40, in <module>
    app.buttons(['Encrypt', 'Cancel'], [encrypt(app.entry('Save as: '),app.entry('Password: ')), app.stop])
  File "/home/skyandstars/Desktop/new_score.py", line 14, in encrypt
    outputFile = "(encrypted)"+filename
TypeError: Can't convert 'Entry' object to str implicitly

2 个答案:

答案 0 :(得分:0)

我检查了

def encrypt(key, filename):
    print(filename, type(filename))

它显示filenametkinter.Entry,而不是字符串,因此您不能在

中添加字符串和Entry
"(encrypted)"+filename

要从Entry获取字符串,必须在所有位置使用filename.get()

outputFile = "(encrypted)" + filename.get()

filesize = str(os.path.getsize( filename.get() )).zfill(16)

或者您可以在函数encrypt的开头进行操作

filename = filename.get()

您对key有相同的问题


编辑:运行代码时,我从tkinter看到其他常见错误。

按钮需要回调-这意味着不带()且不带参数的函数名称-如app.stop-但您使用encrypt(..)。它在开始时运行encrypt(..),并为按钮分配None,因为entry(..)返回None

您可以使用lambda创建不带参数的函数,并分配不包含()的函数

new_function = lambda:encrypt(app.entry('Save as: '), app.entry('Password: '))

[new_function, app.stop]

或直接

[lambda:encrypt(app.entry('Save as: '), app.entry('Password: ')), app.stop]

编辑:另一个错误。您创建了两次条目entry('Save as: ') entry('Password: ')。将显示一对,并在其中输入文字。您在

中创建的第二对
[lambda:encrypt(app.entry('Save as: '), app.entry('Password: ')), app.stop]

但是当您按下按钮时它们是空的,因此您会在函数中得到空字符串。

您只需要使用一对

filename = app.entry('Save as: ', label=True)
key = app.entry("Password", label=True, secret=True)

app.buttons(['Encrypt', 'Cancel'], [lambda:encrypt(key, filename), app.stop])

您甚至可以在此位置使用get()而不是在encrypt内部使用

filename = app.entry('Save as: ', label=True)
key = app.entry("Password", label=True, secret=True)

app.buttons(['Encrypt', 'Cancel'], [lambda:encrypt(key.get(), filename.get()), app.stop])

完整代码

#!/usr/bin/python

import os
from Crypto.Cipher import AES
from Crypto.Hash import SHA256
from Crypto import Random
from appJar import gui
import datetime
import csv

def encrypt(key, filename):

    chunksize = 64*1024

    outputFile = "(encrypted)" + filename
    filesize = str(os.path.getsize(filename)).zfill(16)
    IV = Random.new().read(16)

    encryptor = AES.new(key, AES.MODE_CBC, IV)

    with open(filename, 'rb') as infile:
        with open(outputFile, 'wb') as outfile:
            outfile.write(filesize.encode('utf-8'))
            outfile.write(IV)

            while True:
                chunk = infile.read(chunksize)

                if len(chunk) == 0:
                    break
                elif len(chunk) % 16 != 0:
                    chunk += b' ' * (16 - (len(chunk) % 16))

                outfile.write(encryptor.encrypt(chunk))

with gui('Encryption App', '400x200', font={'size':18}) as app:
    app.label('Simple encryption app')
    app.entry('Type text to encrypt: ', label=True, focus=True)

    filename = app.entry('Save as: ', label=True)
    key = app.entry("Password", label=True, secret=True)
    func = lambda:encrypt(key.get(), filename.get())

    app.buttons(['Encrypt', 'Cancel'], [func, app.stop])

答案 1 :(得分:0)

在appJar中添加小部件时,例如:app.entry('test'),将返回小部件。因此,在您的代码中,当您引用filename时,它指向的是实际的输入框。

如果要在输入框中输入文本,则必须在需要时使用app.getEntry('test')或更新的语法:app.entry('test')

因此,在您的加密函数中,不要使用filename变量,而应使用app.entry('Save as: ')