【问题标题】:Python: Variable not set when process sets itPython:进程设置变量时未设置变量
【发布时间】:2019-09-14 21:26:50
【问题描述】:

其实我不知道我应该给这个问题取什么标题,因为我对 Python 还很陌生,而且这里有一些不同的地方可能会出错。

这个想法是在给定端口的情况下创建一个 websocket 服务器,否则创建一个虚拟实现。

state.py-模块简单而简短:

_dbg = ""

main.py:

import getopt
import multiprocessing
import sys
import time

import state

try:
  (opts, args) = getopt.getopt(sys.argv[1:], "p:", [ "ws-port=" ])
except getopt.GetoptError:
  sys.exit(2)
for (opt, arg) in opts:
  if opt in ("-p", "--ws-port"):
    state.websocketPort = int(arg)

#########
# and now the important part:
#########

if hasattr(state, "websocketPort"):
  def initWebsocketServer():
    print("iWS-1")
    state.websocketServer = WebsocketServer(state.websocketPort)
    print("iWS-2")
    state.websocketServer.run_forever()
    print("iWS-3")
  wsThread = multiprocessing.Process(target = initWebsocketServer, daemon = True)
  wsThread.start()
else:
  print("dummy")
  def dummy(msg):
    pass
  state.websocketServer = type('', (), {})()
  state.websocketServer.send_message_to_all = dummy

time.sleep(10) # not even a sleep makes it work!
state.websocketServer.send_message_to_all("hello")
print("done")

壳牌:

$ python main.py -p 1234
iWS-1
iWS-2
Traceback (most recent call last):
  File "main.py", line 38, in <module>
    state.websocketServer.send_message_to_all("hello")
AttributeError: module 'state' has no attribute 'websocketServer'
$ python main.py
dummy
done
$ 

所以所有ifs,检查和虚拟实现似乎工作正常,但将实际实例分配给模块变量却没有。这里有什么问题?

如果有完全不同或更好的方法,请告诉我。

编辑:
在试图了解不同实体的影响时,我想出了这个:

if hasattr(state, "websocketPort"):
  def initWebsocketServer():
    print("iWS-1")
    print("iWS-2")
    state.websocketServer.run_forever()
    print("iWS-3")
  # this assignment was between the first two print()s earlier:
  state.websocketServer = WebsocketServer(state.websocketPort)
  wsThread = multiprocessing.Process(target = initWebsocketServer, daemon = True)
  wsThread.start()

而且它有效...因为除了调用虚拟化方法之外不会有更多的交互,我想我可以将其作为解决方案。

还是有别的东西坏了?

【问题讨论】:

  • 你没有使用线程,你正在使用进程。进程不共享应用程序状态,包括模块属性。初始和子进程的状态模块是独立的实体。
  • @MisterMiyagi 哦,好的。那么我的 B 计划会是什么样子呢?
  • 要么使用线程,要么在进程之间显式传递消息。多处理文档列出了各种方法。
  • @MisterMiyagi 我想我找到了一个没有消息的解决方案。请查看我的编辑。
  • 考虑改用argparse。来自getopt 文档:“注意 getopt 模块是一个命令行选项解析器,其 API 旨在让 C getopt() 函数的用户熟悉。不熟悉 C getopt() 函数或会喜欢编写更少的代码并获得更好的帮助和错误消息应该考虑使用 argparse 模块。”

标签: python variables module


【解决方案1】:

当hasattr(state, 'websocketPort') 为真时,state.websocketServer 仅在initWebsocketServer 中定义为局部变量,从不在主进程中。

【讨论】:

  • 你说的是第一个版本还是我几分钟后添加的编辑版本?因为我移动了它,它应该在主进程中。
  • 原件。在您的编辑中,您现在使initWebsocketServer(现在更准确地称为startWebsocketServer)在一个非本地名称state 上运行,这实际上是在主进程中初始化的。 然而,每个进程都有自己对我认为是WebsocketServer 的共享实例的引用;结果可能会产生意想不到的副作用。
【解决方案2】:

好吧,原来我编辑的部分也没有工作,它只是没有抛出错误并到达脚本的末尾。这不是我想要它做的全部...... :)

我想我试图做一些不方便的事情hard to do。我切换到常规线程并希望我不会遇到那些进程可以比线程处理得更好的情况......

if hasattr(state, "websocketPort"):
  state.websocketServer = WebsocketServer(state.websocketPort)
  wst = threading.Thread(target = state.websocketServer.run_forever, daemon = True)
  wst.start()
else:
  print("dummy")
  def dummy(msg):
    pass
  state.websocketServer = type('', (), {})()
  state.websocketServer.send_message_to_all = dummy

【讨论】:

    猜你喜欢
    • 2013-09-25
    • 1970-01-01
    • 2015-01-20
    • 1970-01-01
    • 2021-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-11
    相关资源
    最近更新 更多