gpt4 book ai didi

python - 如何在python中的脚本之间共享变量?

转载 作者:IT老高 更新时间:2023-10-28 20:56:13 29 4
gpt4 key购买 nike

以下不起作用

一个

import shared
shared.value = 'Hello'
raw_input('A cheap way to keep process alive..')

py
import shared
print shared.value

在以下两个命令行上运行:
>>python one.py
>>python two.py

(正确的是第二个属性错误)。

有没有一种方法可以做到这一点,即在两个脚本之间共享一个变量?

最佳答案

希望可以在此处写下我对此问题的注释。

首先,我非常欣赏OP中的示例,因为那也是我开始的地方-尽管它使我认为shared是内置的Python模块,直到在[Tutor] Global Variables between Modules ??找到完整的示例为止。

但是,当我寻找“在脚本之间共享变量”(或进程)时-除了Python脚本需要使用其他Python源文件中定义的变量(但不一定是正在运行的进程)的情况下-我大多偶然发现了另外两个用例:

  • 脚本将自身派生到多个子进程中,然后在同一PC上并行运行(可能在多个处理器上)
  • 脚本会产生多个其他子进程,然后这些子进程在同一台PC上并行运行(可能在多个处理器上)

  • 因此,大多数有关“共享变量”和“进程间通信”(IPC)的命中都讨论了这两种情况。但是,在这两种情况下,都可以观察到一个“ parent ”,而“ child ”通常会对其进行引用。

    但是,我感兴趣的是,以单例/单实例模式运行同一脚本的多个调用,它们独立运行,并在它们之间共享数据(如 Python: how to share an object instance across multiple invocations of a script一样)。上面的两种情况并没有真正解决这种问题-相反,它实际上简化为OP中的示例(跨两个脚本共享变量)。

    现在,在Perl中处理此问题时,有 IPC::Shareable;它“允许您将变量绑定(bind)到共享内存”,使用“整数或4个字符串[1]作为跨进程空间的数据的公共(public)标识符”。因此,没有临时文件,也没有网络设置-对于我的用例,我觉得很棒;所以我一直在用Python寻找相同的东西。

    但是,正如 accepted answer by @Drewfer指出的那样:“如果不将信息存储在解释器的两个实例之外的某个地方,您将无法做您想做的事情”;或者换句话说:要么您必须使用网络/套接字设置-要么必须使用临时文件(ergo,“完全分开的python session ”没有共享的RAM)。

    现在,即使有这些考虑,也很难找到可行的示例( pickle除外)-也在 mmapmultiprocessing的文档中。我设法找到了一些其他示例-还描述了文档未提及的一些陷阱:
  • mmap的用法:Sharing Python data between processes using mmap | schmichael's blog中两个不同脚本中的工作代码
  • 演示两个脚本如何更改共享值
  • 请注意,此处将创建一个临时文件作为已保存数据的存储-mmap只是用于访问此临时文件的特殊接口(interface)
  • multiprocessing的用法:工作代码位于:
  • Python multiprocessing RemoteManager under a multiprocessing.Process-具有共享SyncManagermanager.start()(通过Queue)的工作示例;服务器写入,客户端读取(共享数据)
  • Comparison of the multiprocessing module and pyro?-具有共享自定义类的BaseManager(通过server.serve_forever())的工作示例;服务器写入,客户端读取并写入
  • How to synchronize a python dict with multiprocessing-这个答案很好地解释了multiprocessing的陷阱,并且是SyncManager(通过manager.start())与共享字典的工作示例;服务器什么都不做,客户端读写

  • 多亏了这些示例,我提出了一个示例,该示例与 mmap示例基本相同,并采用了“同步python dict”示例中的方法-将 BaseManager(通过 manager.start()通过文件路径地址)与共享列表一起使用;服务器和客户端均可读写(粘贴在下面)。注意:
  • multiprocessing管理器可以通过manager.start()server.serve_forever()启动
  • serve_forever()锁-start()
  • multiprocessing中有自动记录功能:似乎可以与start() ed进程配合使用-但似乎忽略了serve_forever()
  • multiprocessing中的地址规范可以是IP(套接字)或临时文件(可能是管道?)路径;在multiprocessing文档中:
  • 大多数示例都使用multiprocessing.Manager()-这只是一个函数(不是类实例化),它返回SyncManager,它是BaseManager的特殊子类;并使用start()-但在独立运行的脚本之间不用于IPC;这里使用文件路径
  • 在独立运行的脚本之间,用于IPC的其他示例serve_forever()方法很少。这里使用IP/套接字地址
  • 如果未指定地址,则将自动使用临时文件路径(有关如何查看此示例,请参见16.6.2.12. Logging)

  • 除了“同步python字典”文章中的所有陷阱之外,如果有列表,还有其他陷阱。该帖子指出:

    All manipulations of the dict must be done with methods and not dict assignments (syncdict["blast"] = 2 will fail miserably because of the way multiprocessing shares custom objects)


    dict['key']获取和设置的解决方法是使用 dict公共(public)方法 getupdate。问题是没有像 list[index]这样的替代方法。因此,对于共享列表,我们还必须将 __getitem____setitem__方法(它们是 list私有(private)的)注册为 exposed,这意味着我们还必须重新注册 list:/的所有公共(public)方法

    好吧,我认为那是最关键的事情。这是两个脚本-它们可以只在单独的终端中运行(服务器优先);在Linux上使用Python 2.7开发的注释:
    a.py(服务器):
    import multiprocessing
    import multiprocessing.managers

    import logging
    logger = multiprocessing.log_to_stderr()
    logger.setLevel(logging.INFO)


    class MyListManager(multiprocessing.managers.BaseManager):
    pass


    syncarr = []
    def get_arr():
    return syncarr

    def main():

    # print dir([]) # cannot do `exposed = dir([])`!! manually:
    MyListManager.register("syncarr", get_arr, exposed=['__getitem__', '__setitem__', '__str__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort'])

    manager = MyListManager(address=('/tmp/mypipe'), authkey='')
    manager.start()

    # we don't use the same name as `syncarr` here (although we could);
    # just to see that `syncarr_tmp` is actually <AutoProxy[syncarr] object>
    # so we also have to expose `__str__` method in order to print its list values!
    syncarr_tmp = manager.syncarr()
    print("syncarr (master):", syncarr, "syncarr_tmp:", syncarr_tmp)
    print("syncarr initial:", syncarr_tmp.__str__())

    syncarr_tmp.append(140)
    syncarr_tmp.append("hello")

    print("syncarr set:", str(syncarr_tmp))

    raw_input('Now run b.py and press ENTER')

    print
    print 'Changing [0]'
    syncarr_tmp.__setitem__(0, 250)

    print 'Changing [1]'
    syncarr_tmp.__setitem__(1, "foo")

    new_i = raw_input('Enter a new int value for [0]: ')
    syncarr_tmp.__setitem__(0, int(new_i))

    raw_input("Press any key (NOT Ctrl-C!) to kill server (but kill client first)".center(50, "-"))
    manager.shutdown()

    if __name__ == '__main__':
    main()
    b.py(客户端)
    import time

    import multiprocessing
    import multiprocessing.managers

    import logging
    logger = multiprocessing.log_to_stderr()
    logger.setLevel(logging.INFO)


    class MyListManager(multiprocessing.managers.BaseManager):
    pass

    MyListManager.register("syncarr")

    def main():
    manager = MyListManager(address=('/tmp/mypipe'), authkey='')
    manager.connect()
    syncarr = manager.syncarr()

    print "arr = %s" % (dir(syncarr))

    # note here we need not bother with __str__
    # syncarr can be printed as a list without a problem:
    print "List at start:", syncarr
    print "Changing from client"
    syncarr.append(30)
    print "List now:", syncarr

    o0 = None
    o1 = None

    while 1:
    new_0 = syncarr.__getitem__(0) # syncarr[0]
    new_1 = syncarr.__getitem__(1) # syncarr[1]

    if o0 != new_0 or o1 != new_1:
    print 'o0: %s => %s' % (str(o0), str(new_0))
    print 'o1: %s => %s' % (str(o1), str(new_1))
    print "List is:", syncarr

    print 'Press Ctrl-C to exit'
    o0 = new_0
    o1 = new_1

    time.sleep(1)


    if __name__ == '__main__':
    main()

    最后,在Linux上创建了 /tmp/mypipe,但是它是0字节,并具有 srwxr-xr-x属性(用于套接字);我想这让我很高兴,因为我既不必担心网络端口,也不必担心像 :)这样的临时文件

    其他相关问题:
  • Python: Possible to share in-memory data between 2 separate processes(很好的解释)
  • Efficient Python to Python IPC
  • Python: Sending a variable to another script
  • 关于python - 如何在python中的脚本之间共享变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1829116/

    29 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com