【发布时间】: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 模块。”