exec:名称未定义,但可以在同一代码中更早地使用

时间:2019-08-31 15:41:29

标签: python-3.x exchangelib python-exec

我在创建一个脚本时遇到了这个问题,该脚本将目录和邮件导出到具有exchangelib的另一个帐户。

当我使用“ exec”运行代码时,它返回的值未定义,但在同一代码中更早地起作用了。

这部分无效:

exec('a = van_account.inbox / ' + par + ' / ' + '"%s"' % fol + '; b = a.all().only("id", "changekey"); data = van_account.export(b); up = naar_account.upload((naar_account.inbox / ' + par + ' / ' + '"%s"' % fol + ', d) for d in data); print("[UPLOAD] %i mail geupload in %s" % (len(data), fol))')

此部分就在它上面,并且可以正常工作。 这也指“ naar_account”:

code = "create = Folder(parent=naar_account.inbox / "
par = ' '.join('"{}" /'.format(word) for word in par.split('/'))[:-1]

exec(code + par + ', name="%s"); create.save()' % fol)

这也有效:

exec('print(naar_account)')

即使重命名也可以,并且还说未定义重命名的部分:

exec('wtf = naar_account; a = van_account.inbox / ' + par + ' / ' + '"%s"' % fol + '; b = a.all().only("id", "changekey"); data = van_account.export(b); up = wtf.upload((wtf.inbox / ' + par + ' / ' + '"%s"' % fol + ', d) for d in data); print("[UPLOAD] %i mail geupload in %s" % (len(data), fol))')

完整代码:

def search_levels(van_account, naar_account):
    for subfolder in van_account.inbox.walk():
        subfolder = subfolder.absolute

        # If '/' means it has subfolders
        if '/' in subfolder.replace(van_account.inbox.absolute + '/', ''):
            # Strip fill path, leave only Inbox path
            par = subfolder.replace(van_account.inbox.absolute + '/', '')
            # Get last item, it's the Dir we need to create
            fol = par.split('/')[-1]
            # Replace last item, it's the Dir, we only need the parent
            par = par.replace(par.split('/')[-1], '')[:-1]

            code = "create = Folder(parent=naar_account.inbox / "
            par = ' '.join('"{}" /'.format(word) for word in par.split('/'))[:-1]

            exec(code + par + ', name="%s"); create.save()' % fol)
            print('[Created] %s' % fol)

            exec('print(naar_account)')

            exec('a = van_account.inbox / ' + par + ' / ' + '"%s"' % fol + '; b = a.all().only("id", "changekey"); data = van_account.export(b); up = naar_account.upload((naar_account.inbox / ' + par + ' / ' + '"%s"' % fol + ', d) for d in data); print("[UPLOAD] %i mail geupload in %s" % (len(data), fol))')

        else:
            par = None
            fol = subfolder.replace(van_account.inbox.absolute + '/', '')

            create = Folder(parent=naar_account.inbox, name=fol)
            create.save()
            print('[Created] %s' % fol)

            a =  van_account.inbox / fol
            b = a.all().only('id', 'changekey')
            data = van_account.export(b)
            up = naar_account.upload((naar_account.inbox / fol, d) for d in data)
            print('[UPLOAD] %i mail geupload naar %s' % (len(data), fol))

Traceback (most recent call last):
  File "./migrate.py", line 225, in <module>
    start(van_adres, van_passwd, naar_adres, naar_passwd)
  File "./migrate.py", line 114, in start
    search_levels(van_account, naar_account)
  File "./migrate.py", line 154, in search_levels
    exec('a = van_account.inbox / ' + par + ' / ' + '"%s"' % fol + '; b = a.all().only("id", "changekey"); data = van_account.export(b); wtf = naar_account; up = wtf.upload((wtf.inbox / ' + par + ' / ' + '"%s"' % fol + ', d) for d in data); print("[UPLOAD] %i mail geupload in %s" % (len(data), fol))')
  File "<string>", line 1, in <module>
  File "/usr/local/lib/python3.7/site-packages/exchangelib/account.py", line 340, in upload
    is_empty, data = peek(data)
  File "/usr/local/lib/python3.7/site-packages/exchangelib/util.py", line 130, in peek
    first = next(iterable)
  File "<string>", line 1, in <genexpr>
NameError: name 'wtf' is not defined

1 个答案:

答案 0 :(得分:1)

wtf用于exec的范围,但似乎没有其他地方,exec本身在本地范围。因此,wtf将是exec范围内的局部变量。在exec之外对本地人的修改是不可见的,因此wtf根本无法从exec的范围之外访问。

生成器表达式中的名称(最左边的for表达式除外)在调用__next__时会延迟计算。因此,在调用wtf时将查找wtf.inbox中的__next__

这发生在exec范围之外的其他某些函数中,因此在该地方找不到wtf,后者是后者的本地变量。