2015-08-07 1 views
1

Я оцениваю укроп, и я хочу знать, обрабатывается ли этот сценарий. У меня есть случай, когда я успешно импортирую модуль в процесс python. Могу ли я использовать укроп для сериализации, а затем загружать этот модуль в другой процесс с другим sys.path, который не включает этот модуль? Прямо сейчас я получаю неудачи импорта, но, возможно, я делаю что-то неправильно.Выполняет ли модуль python укропа при импорте модулей, когда sys.path отличается?

Вот пример. Я запустить этот сценарий, где путь модуля foo.py находится в моем sys.path:

% cat dill_dump.py 
import dill 
import foo 
myFile = "./foo.pkl" 
fh = open(myFile, 'wb') 
dill.dump(foo, fh) 

Теперь я бегу этот сценарий, где у меня нет каталога foo.py в моем PYTHONPATH:

% cat dill_load.py 
import dill 
myFile = "./foo.pkl" 
fh = open(myFile, 'rb') 
foo = dill.load(fh) 
print foo 

Она терпит неудачу с этой трассировки стека:

Traceback (most recent call last): 
    File "dill_load.py", line 4, in <module> 
    foo = dill.load(fh) 
    File "/home/b/lib/python/dill-0.2.4-py2.6.egg/dill/dill.py", line 199, in load 
    obj = pik.load() 
    File "/rel/lang/python/2.6.4-8/lib/python2.6/pickle.py", line 858, in load 
    dispatch[key](self) 
    File "/rel/lang/python/2.6.4-8/lib/python2.6/pickle.py", line 1133, in load_reduce 
    value = func(*args) 
    File "/home/b/lib/python/dill-0.2.4-py2.6.egg/dill/dill.py", line 678, in _import_module 
    return __import__(import_name) 
ImportError: No module named foo 

Так что, если мне нужно иметь один и тот же путь питона между двумя процессами, то какой смысл сериализации модуль питона? Или, другими словами, есть ли какое-либо преимущество в загрузке foo через укроп, только имея вызов «import foo»?

ответ

0

Это интересный провал. Обратите внимание, что если вы сделаете dill.dumps(foo), вы получите содержимое модуля foo ... сбой части - это использование встроенного крючка импорта python (__import__), чтобы сделать немного больше, чем зарегистрировать модуль в sys.modules. Должно быть возможно обойти это и изменить dill, чтобы модуль мог быть импортирован, если модуль не найден в PYTHONPATH. Тем не менее, я действительно считаю, что модуль должен быть найден в PYTHONPATH ... это то, что ожидается от модуля ... поэтому я не уверен, что это хорошая идея. Но это может быть ...

Как было отмечено выше, для файла foo.py, с содержанием: hello = "hello world, I am foo"

>>> import dill 
>>> import foo 
>>> dill.dumps(foo) 
'\x80\x02cdill.dill\n_import_module\nq\x00U\x03fooq\x01\x85q\x02Rq\x03}q\x04(U\x08__name__q\x05h\x01U\x08__file__q\x06U\x06foo.pyq\x07U\x05helloq\x08U\x15hello world, I am fooq\tU\x07__doc__q\nNU\x0b__package__q\x0bNub.' 

Вы можете увидеть содержимое файла сохраняется в рассоле.

Основная причина использования dill с модулями заключается в том, что dill может записывать динамические модификации модулей. Например, добавление функции или другой объект:

>>> import foo 
>>> import dill 
>>> foo.a = 100 
>>> with open('foo.pkl', 'w') as f: 
... dill.dump(foo, f) 
... 
>>> 

Тогда перезапутить ... (с foo в PYTHONPATH)

Python 2.7.10 (default, May 25 2015, 13:16:30) 
[GCC 4.2.1 Compatible Apple LLVM 5.1 (clang-503.0.40)] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import dill 
>>> with open('foo.pkl', 'r') as f: 
... foo = dill.load(f) 
... 
>>> foo.hello 
'hello world, I am foo' 
>>> foo.a 
100 
>>> 

я добавил это как запрос отчета об ошибке/особенность: https://github.com/uqfoundation/dill/issues/123

+0

Одно из предложений о том, как реализовать это, - это захват sys.path в сериализованном потоке данных, чтобы вы знали, где при загрузке появился модуль _foo_. Это было бы полезно в том, что это позволило бы увеличить переносимость состояния python, где вы могли бы загрузить сеанс python на машинах или оболочках с разными настройками. –

+0

@BrentV: Хорошая идея. Эта информация действительно должна быть в атрибуте '__file__'. Итак, 'foo .__ file__' скажет вам, откуда он был загружен. Это можно было бы использовать только на том же компьютере, конечно, так что это не полностью портативное решение. Я шел по линиям захвата всего кода модуля с помощью 'inspect' или' dill.source.getsource'. –