【问题标题】:Calling methods from an already running python script从已经运行的 python 脚本调用方法
【发布时间】:2013-05-22 08:24:39
【问题描述】:

我是 python 新手,并且已经为此苦苦挣扎了很长一段时间。好的,所以我有一个程序可以登录到服务器,然后每 10 秒不断地 ping 服务器,以查看服务器的状态是否已更改。在同一个脚本中,我有一个向服务器发送消息的函数。

发送方法的简单示例:

def send(self, message):

   url = ("https://testserver.com/socket?message=%s") % (message)

   req = urllib2.Request(url, None, None)
   response = urllib2.urlopen(req).read()

   print response

我可以在另一个脚本运行时从另一个脚本调用这个方法吗?就像使用同一个会话一样。似乎当我运行调用此函数的脚本时,它会创建它的一个新实例,而不是使用该脚本的当前实例,导致它抛出我的异常,说我没有连接到服务器。

很抱歉这个菜鸟问题。我已经尝试谷歌搜索了一段时间,但我似乎无法找到答案。我已阅读以下内容,但这些并没有解决问题:

Python call function within class

Python code to get current function into a variable?

您好 @nFreeze 感谢您的回复,我尝试使用 ZeroRPC,但每次运行您提供的脚本/示例(显然已编辑)时,都会遇到此错误:

Traceback (most recent call last):
    File "C:\Users\dwake\Desktop\Web Projects\test.py", line 1, in <module>
import zerorpc
    File "C:\Python27\lib\site-packages\zerorpc\__init__.py", line 27, in <module>
from .context import *
    File "C:\Python27\lib\site-packages\zerorpc\context.py", line 29, in <module>
import gevent_zmq as zmq
    File "C:\Python27\lib\site-packages\zerorpc\gevent_zmq.py", line 33, in <module>
import gevent.event
    File "C:\Python27\lib\site-packages\gevent\__init__.py", line 48, in <module>
from gevent.greenlet import Greenlet, joinall, killall
    File "C:\Python27\lib\site-packages\gevent\greenlet.py", line 6, in <module>
from gevent.hub import greenlet, getcurrent, get_hub, GreenletExit, Waiter
    File "C:\Python27\lib\site-packages\gevent\hub.py", line 30, in <module>
greenlet = __import__('greenlet').greenlet
ImportError: No module named greenlet

即使我已经安装了 gevent。我不确定如何解决这个问题。现在已经用谷歌搜索了一个小时。

【问题讨论】:

  • 一种简单的方法是让两个线程在同一进程中同时运行,一个 ping 服务器,另一个执行您喜欢的任何其他逻辑。多线程意味着执行的两个“线程”都被分配了公平分配的 CPU 时间,并共享相同的内存和进程空间。或者,您可以让脚本 A 写入文件,脚本 B 检查文件是否有更新,或一些类似的机制(sqlite 数据库、管道...)
  • ...但是你应该明白的是,你的心智模式需要纠正。默认情况下,正在运行的程序(在本例中为 python 程序)不会自动成为某种智能代理,可以自动与其他程序对话并以适当的值响应它们。默认情况下,程序只知道它们内部发生了什么以及它们自己决定要与之交互的内容。
  • 谢谢 我实际上已经编写了大约一年的 java 程序。具有 c# 和 perl 知识。我知道程序不会立即小 HAL 9000nd's。感谢您指出这一点,尽管它很有建设性。我需要做的是将参数传递给已经创建的方法实例。我打算尝试使用删除的文件,但这会变得很乱,除非我编写一个清理过程(更多代码无用)。

标签: python python-2.7 python-3.x gevent greenlets


【解决方案1】:

您要查找的内容称为RPC 服务器。它允许外部客户端在您的应用程序中执行公开的功能。幸运的是,python 有很多 RPC options。 ZeroRPC 可能是我最喜欢的,因为它易于使用并且支持 node.js。以下是如何使用 ZeroRPC 公开发送方法的示例:

在您的应用(服务器)中

import zerorpc

class HelloRPC(object):
    def send(self, message):
        url = ("https://testserver.com/socket?message=%s") % (message)
        req = urllib2.Request(url, None, None)
        response = urllib2.urlopen(req).read()
        return response    
s = zerorpc.Server(HelloRPC())
s.bind("tcp://0.0.0.0:4242")
s.run()

在其他应用(客户端)中

import zerorpc

c = zerorpc.Client()
c.connect("tcp://127.0.0.1:4242")
print c.send("RPC TEST!")

【讨论】:

  • @MethodMan - 你在运行什么操作系统?
  • 嗨,正在运行窗口。我终于设法使用预编译版本修复它,但现在我遇到了“LostRemote:10 秒心跳后丢失远程”异常。不知道我是否把电话打错了地方。我现在正在测试:) 感谢您的帮助。如果我能正常工作,我会告诉你的。
  • 嗯,当我去地址时,我应该能够 ping 它或获得某种 wsdl 吗?
  • 它使用 tcp,因此请确保您的防火墙没有阻塞。在 def send 处设置一个断点,看看它是否命中了方法。您可以在同一个盒子上使用command line client 进行测试。
  • 如果他们的示例有效,那么您的 send 方法可能会引发错误。换个 try except 并返回消息确认
【解决方案2】:

最简单的方法是使用 UNIX 信号。您不需要第三方库。

# your-daemon.py
import signal
from time import sleep

def main():
    while True:
        print "Do some job..."
        sleep(5)

def send():
    print "Send your data"

def onusr1(*args):
    send()

if __name__ == '__main__':
    signal.signal(signal.SIGUSR1, onusr1)
    main()

在终端运行:

$ pgrep -f your-daemon.py | xargs kill -SIGUSR1

当然,这只适用于本地机器。此外,您不能为 send 函数指定任何参数,如果您想拥有多个处理程序,请按照以下建议使用 RPC。

【讨论】:

    猜你喜欢
    • 2014-04-21
    • 1970-01-01
    • 1970-01-01
    • 2015-09-05
    • 2016-07-21
    • 2019-12-31
    • 1970-01-01
    • 1970-01-01
    • 2014-02-09
    相关资源
    最近更新 更多