1

matlabロードおよび保存機能を模倣しようとしています。私はこのスレッドに従っています: Shelve Code gets KeyError

スマートです。ただし、そのコードを別のモジュールに記述し、そのモジュールをインポートしてその関数を呼び出そうとすると、グローバル変数にアクセスできません。

具体的には、私は書いてhappy.py、内部に関数を持っています:

def save(filename='tmp', globals_=None):
    if globals_ is None:
        globals_ = globals()
        
    globals()
    import shelve
    my_shelf = shelve.open(filename, 'n')
    for key, value in globals_.items():
        if not key.startswith('__'):
            try:
                my_shelf[key] = value
            except Exception:
                print('ERROR shelving: "%s"' % key)
            else:
                print('shelved: "%s"' % key)
    my_shelf.close()

def load(filename='tmp', globals_=None):
    import shelve
    my_shelf = shelve.open(filename)
    for key in my_shelf:
        globals()[key] = my_shelf[key]
    my_shelf.close()

そして試してみると

a = 1
b = 2
happy.save()

それはセーブab.

これはglobal()、モジュールの外側にオブジェクトを渡さないからですか? その時やりたいことはどうすればいいの?

4

3 に答える 3

1

以下は、別のモジュールとして機能します。

import shelve
import sys
import types

EXCLUDED_TYPES = (types.ModuleType,)  # Everything can't be shelved.

def save(filename='tmp', globals_=None):
    if globals_ is None:
        globals_ = sys._getframe(1).f_globals  # Caller's globals.

    with shelve.open(filename, 'n') as my_shelf:
        for key, value in globals_.items():
            if not (key.startswith('__') or isinstance(value, EXCLUDED_TYPES)):
                try:
                    my_shelf[key] = value
                except Exception as e:
                    print('ERROR shelving: "%s"' % key, 'Exception:', e)
                else:
                    print('shelved: "%s"' % key)

def load(filename='tmp', globals_=None):
    if globals_ is None:
        globals_ = sys._getframe(1).f_globals  # Caller's globals.

    with shelve.open(filename) as my_shelf:
        for key in my_shelf:
            globals_[key]=my_shelf[key]
            print('unshelved: "%s"' % key)

一般的に言えば、関数がこのようにグローバル変数を作成するのは良い考えではないと思います。load()また、呼び出し元の名前空間内の既存の値をサイレントに変更する可能性があることに注意してください。

に加えて、ロードされたすべてのモジュールに関連付けられているため、すべてのグローバル名前空間を簡単に保存することはできません__main__。本当にやりたい場合は、 の内容を繰り返し処理することで実現できる可能性がありますsys.modules

于 2013-04-01T18:37:50.780 に答える
0

このコードをコンソールに貼り付けても問題はありません。

>>> def save(filename='tmp',globals_=None):
...     import shelve
...     globals_ = globals_ or globals()
...     my_shelf=  shelve.open(filename, 'n')
...     for key, value in globals_.items():
...         if not key.startswith('__'):
...             try:
...                 my_shelf[key] = value
...             except Exception:
...                 print('ERROR shelving: "%s"' % key)
...             else:
...                 print('shelved: "%s"' % key)
...     my_shelf.close()
... 
>>> def load(filename='tmp',globals_=None):
...     import shelve
...     my_shelf = shelve.open(filename)
...     for key in my_shelf:
...         globals()[key]=my_shelf[key]
...     my_shelf.close()
... 
>>> a, b = 1, 2
>>> save()
shelved: "load"
shelved: "a"
shelved: "b"
shelved: "save"

その後:

>>> def save(filename='tmp',globals_=None):
...     import shelve
...     globals_ = globals_ or globals()
...     my_shelf=  shelve.open(filename, 'n')
...     for key, value in globals_.items():
...         if not key.startswith('__'):
...             try:
...                 my_shelf[key] = value
...             except Exception:
...                 print('ERROR shelving: "%s"' % key)
...             else:
...                 print('shelved: "%s"' % key)
...     my_shelf.close()
... 
>>> def load(filename='tmp',globals_=None):
...     import shelve
...     my_shelf = shelve.open(filename)
...     for key in my_shelf:
...         globals()[key]=my_shelf[key]
...     my_shelf.close()
... 
>>> load()
>>> a, b
(1, 2)

しかし、それをモジュールとして使用すると少し奇妙です:

>>> from happy import *
>>> a, b
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
>>> load()
>>> a, b
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
>>> happy.a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'happy' is not defined
>>> from happy import *
>>> a, b
(1, 2)

ここで回避策を講じるのに十分ですか?

于 2013-04-01T17:47:12.360 に答える
0

スタックを参照するために使用できinspectます。私が定義したこのばかげた (不適切な名前の関数) は、広範囲にテストしていませんが、呼び出し元の名前空間からグローバル変数を取得するのに問題ないようです。また、さまざまな python 実装で動作するかどうかもわかりません。inspect.currentframe(関数は間違いなく実装に依存するため、これについて言及します)。価値があるため、Cpythonで問題なく動作するようです。

import inspect
def save(globals=None):
    if globals is None:
        frames = inspect.stack()
        caller_frame = frames[-1][0]
        globals = dict((k,v) for (k,v) in caller_frame.f_globals.items() if not k.startswith('__'))
    return globals


if __name__ == "__main__":
    a = 1
    b = 2
    print save()
于 2013-04-01T17:39:10.247 に答える