pickle doesn't work in compile/exec - python

I want to use pickle in compile/exec, but it doesn't work for me. It only works when I use the global namespace. But I don't want to use global namespace, is there any way for that ? Thanks
>>> a = compile("def f():\n\t'hello'\nimport pickle\npickle.dumps(f)", "<stdin>", "exec")
>>> exec(a) # works
>>> exec(a, {}) # fails
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in <module>
_pickle.PicklingError: Can't pickle <function f at 0x1050881e0>: it's not the same object as __main__.f
>>> exec(a, {'__name__': '__main__'}) # fails too
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in <module>
_pickle.PicklingError: Can't pickle <function f at 0x1050882f0>: it's not the same object as __main__.f

No, there is no way to do this (nothing reasonable anyway). Functions pickle by qualified name, they don't actually pickle any part of their implementation. They unpickle by simply importing the module they were defined in and loading the name in question. If there is no namespace to find the function on (you replaced the globals of __main__ with your own custom dict that has no ties to __main__'s globals), you can't pickle it, because __main__.f (the qualified name of f) doesn't exist in the globals of __main__.

Related

Python Package addict force error if not existing

The package addict allows you to use dicts through attribute setting:
Example from the website:
from addict import Dict
body = Dict()
body.query.filtered.query.match.description = 'addictive'
body.query.filtered.filter.term.created_by = 'Mats'
Now when when I use for example a = body.B and I haven't included B yet it does not throw an error, but just returns nothing. How can I make it throw an error when the attribute was net yet set?
addict.Dict implements the __missing__ method to generate a value for any missing key(/attribute); the current implementation generates a new Dict instance. If you don't want this behaviour, you'll have to override it:
class MyDict(Dict):
def __missing__(self, name):
raise KeyError(name)
Note that this will throw a KeyError for attribute access, which may be confusing; you could also override __getattr__ if you want to throw an AttributeError instead. In use:
>>> body = MyDict()
>>> body.B
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "path/to/addict.py", line 62, in __getattr__
return self.__getitem__(item)
File "<stdin>", line 3, in __missing__
KeyError: 'B'
>>> body.B = "hello"
>>> body.B
'hello'
Note also that this will break the other examples you showed as well, as e.g. foo.bar.baz = qux calls __getattr__ on foo before calling __setattr__ on foo.bar (if successful):
>>> body.query.filtered.query.match.description = 'addictive'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "path/to/addict.py", line 62, in __getattr__
return self.__getitem__(item)
File "<stdin>", line 3, in __missing__
KeyError: 'query'

Modules imported using `exec` are not available if imported by a function

In Python 3, when I import a module using exec in the global scope, it works. But when I do it within a function, even though I get no import error, Python does not recognize the module name.
Importing and using sys successfully, in the global scope:
>>> sys.argv
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'sys' is not defined
>>> exec('import sys')
>>> sys.argv
['']
No import error, though cannot use os which has been imported from a function:
>>> def import_os():
... exec('import os')
... os.listdir('.')
...
>>> import_os()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in import_os
NameError: name 'os' is not defined
>>>
Any idea how to make this work from within a function?

Pydoc not working in Python 3.3 in Windows

I am trying to generate the help text at runtime and i am not able to use the pydoc command in Windows. When i type
>>> pydoc(atexit)
Traceback (most recent call last):
File "<console>", line 1, in <module>
NameError: name 'pydoc' is not defined
I have already set up the environment variables for pydoc.py file. C:\Python33\Lib\pydoc.py.
This also not works like it works for >>help('atexit')
>>> pydoc('atexit')
Traceback (most recent call last):
File "<console>", line 1, in <module>
NameError: name 'pydoc' is not defined
Whats the possible reason for it.
Updates:
>>> import pydoc
>>> pydoc(sys)
Traceback (most recent call last):
File "<console>", line 1, in <module>
TypeError: 'module' object is not callable
>>> pydoc('sys')
Traceback (most recent call last):
File "<console>", line 1, in <module>
TypeError: 'module' object is not callable
Like any library in Python, you need to import it before you can use it.
Edit What exactly are you trying to achieve? Modules are indeed not callable. pydoc.help is the function you want, although I don't really know why you need it, since as you note the standalone help function does the same thing already.

from A.B import X using __import__?

Let's say A is a package directory, B is a module within the directory, and X is a function or variable written in B. How can I import X using the __import__() syntax? Using scipy as an example:
What I want:
from scipy.constants.constants import yotta
What doesn't work:
>>> __import__("yotta", fromlist="scipy.constants.constants")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named yotta
>>> __import__("yotta", fromlist=["scipy.constants.constants"])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named yotta
>>> __import__("yotta", fromlist=["scipy","constants","constants"])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named yotta
>>> __import__("scipy.constants.constants.yotta", fromlist=["scipy.constants.constats"])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named yotta
Any suggestions would be much appreciated.
The python import statement performs two tasks: loading the module and makeing it available in the namespace.
import foo.bar.baz
will provide the name foo in the namespace, not baz, so __import__ will give you foo
foo = __import__('foo.bar.baz')
On the other hand
from foo.bar.baz import a, b
does not make a module available, but what the import statement needs to perform the assignmaents is baz. this corresponds to
_tmp_baz = __import__('foo.bar.baz', fromlist=['a', 'b'])
a = _tmp_baz.a
b = _tmp_baz.b
without making the temporary visible, of course.
the __import__ function does not enforce the presence of a and b, so when you want baz you can just give anything in the fromlist argument to put __import__ in the "from input" mode.
So the solution is the following. Assuming 'yotta' is given as a string variable, I have used getattr for attribute access.
yotta = getattr(__import__('scipy.constants.constants',
fromlist=['yotta']),
'yotta')
__import__("scipy.constants.constants", fromlist=["yotta"])
The argument fromlist is equivalent to the right hand side of from LHS import RHS.
From the docs:
__import__(name[, globals[, locals[, fromlist[, level]]]])
[...]
The fromlist gives the names of objects or submodules that should be imported from the module given by name.
[...]
On the other hand, the statement from spam.ham import eggs, sausage as saus results in
_temp = __import__('spam.ham', globals(), locals(), ['eggs', 'sausage'], -1)
eggs = _temp.eggs
saus = _temp.sausage
(Emphasis mine.)

Making a module global?

I would like to know why
>>> def func2():
... global time
... import time
...
>>> time
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'time' is not defined
>>> func2()
>>> time
<module 'time' (built-in)>
>>>
works, but
>>> def func():
... global module
... module="time"
... exec ("global %s" %module)
... exec ("import %s" %module)
...
>>> time
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'time' is not defined
>>> func()
>>> time
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'time' is not defined
works not, and how i could get it to work =)
thank you
Each of your exec() calls happens in a separate namespace. Abandon this path; it will only lead to ruin.
Because exec uses its own scope by default. If you do exec "global {0}; import {0}".format(module) in globals(), then it'll work.
You shouldn't be doing that, unless you really need to.
To import a module given the name as a string use
time=__import__('time')
Here's one way you might use it
usermodulenames = ["foo","bar","baz"]
usermodules = dict((k,__import__(k)) for k in usermodulenames)
What you are trying to do is either very sophisticated or very odd. This is how it works:
exec ("import %s" % module) in globals()
Please describe the bigger problem you are trying to solve

Categories