I ran into this when creating a script that exports dirs and mails to another account with exchangelib.
When I run code with "exec" it returns as not defined but earlier on in the same code it works.
This part doesn't work:
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))')
This part is right above it and does work. This also refers to "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)
This also works:
exec('print(naar_account)')
Even renaming it works and than it says the renamed part is not defined:
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))')
Full code:
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
wtfis used in theexec's scope but seemingly nowhere else, withexecitself in a local scope. Thereforewtfwill be a local variable in theexecscope. Modifications of the locals throughexecare not visible outside of it, thereforewtfis not accessible from outside theexec's scope at all.Names in generator expressions (with the exception of the left-most
forexpression) are evaluated lazily when__next__is called. Thereforewtffromwtf.inboxwill be looked up when__next__is called.That happens in some other function outside the
execscope and thereforewtf, being local to the latter, is not found there.