与longlunning python脚本交互

2024-04-20 11:13:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个长时间运行的Python脚本,它收集来自Twitter的tweets,我想知道每隔一段时间它是如何运行的。在

目前,我正在使用signal库捕捉中断,此时我调用print函数。像这样:

import signal

def print_info(count):
    print "#Tweets:", count

#Print out the process ID so I can interrupt it for info
print 'PID:', os.getpid()

#Start listening for interrupts
signal.signal(signal.SIGUSR1, functools.partial(print_info, tweet_count))

每当我需要我的信息时,我打开一个新的终端并发出我的中断:

^{pr2}$

有更好的方法吗?我知道我可以在预定的时间间隔内编写脚本,但我更感兴趣的是了解随需应变,以及可能发出其他命令。在


Tags: the函数importinfo脚本forsignaldef
3条回答

我个人把信息写到一个文件中,这样我就可以得到它了,尽管这样做的缺点是速度可能会稍微慢一点,因为它必须在每次或每隔几次检索tweet时写入一个文件。在

如果您可以在cd2>中输入一个文件{cd3>,那么您可以在cd2}中输入任何一行。如果你想停下来,只要Ctrl-C。在

向进程发送信号会中断进程。下面您将找到一种使用专用线程来模拟python控制台的方法。控制台作为unix套接字公开。在

import traceback
import importlib
from code import InteractiveConsole
import sys
import socket
import os
import threading
from logging import getLogger

# template used to generate file name
SOCK_FILE_TEMPLATE = '%(dir)s/%(prefix)s-%(pid)d.socket'

log = getLogger(__name__)


class SocketConsole(object):
    '''
    Ported form :eventlet.backdoor.SocketConsole:.
    '''
    def __init__(self, locals, conn, banner=None):  # pylint: diable=W0622
        self.locals = locals
        self.desc = _fileobject(conn)
        self.banner = banner
        self.saved = None

    def switch(self):
        self.saved = sys.stdin, sys.stderr, sys.stdout
        sys.stdin = sys.stdout = sys.stderr = self.desc

    def switch_out(self):
        sys.stdin, sys.stderr, sys.stdout = self.saved

    def finalize(self):
        self.desc = None

    def _run(self):
        try:
            console = InteractiveConsole(self.locals)
            # __builtins__ may either be the __builtin__ module or
            # __builtin__.__dict__ in the latter case typing
            # locals() at the backdoor prompt spews out lots of
            # useless stuff
            import __builtin__
            console.locals["__builtins__"] = __builtin__
            console.interact(banner=self.banner)
        except SystemExit:  # raised by quit()
            sys.exc_clear()
        finally:
            self.switch_out()
            self.finalize()


class _fileobject(socket._fileobject):
    def write(self, data):
        self._sock.sendall(data)

    def isatty(self):
        return True

    def flush(self):
        pass

    def readline(self, *a):
        return socket._fileobject.readline(self, *a).replace("\r\n", "\n")


def make_threaded_backdoor(prefix=None):
    '''
    :return: started daemon thread running :main_loop:
    '''
    socket_file_name = _get_filename(prefix)

    db_thread = threading.Thread(target=main_loop, args=(socket_file_name,))
    db_thread.setDaemon(True)
    db_thread.start()
    return db_thread


def _get_filename(prefix):
    return SOCK_FILE_TEMPLATE % {
        'dir': '/var/run',
        'prefix': prefix,
        'pid': os.getpid(),
    }


def main_loop(socket_filename):
    try:
        log.debug('Binding backdoor socket to %s', socket_filename)
        check_socket(socket_filename)

        sockobj = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        sockobj.bind(socket_filename)
        sockobj.listen(5)
    except Exception, e:
        log.exception('Failed to init backdoor socket %s', e)
        return

    while True:
        conn = None
        try:
            conn, _ = sockobj.accept()
            console = SocketConsole(locals=None, conn=conn, banner=None)
            console.switch()
            console._run()
        except IOError:
            log.debug('IOError closing connection')
        finally:
            if conn:
                conn.close()


def check_socket(socket_filename):
    try:
        os.unlink(socket_filename)
    except OSError:
        if os.path.exists(socket_filename):
            raise

示例程序:

^{pr2}$

示例会话:

mmatczuk@cactus:~$ rlwrap nc -U /var/run/test-3196.socket
Python 2.7.6 (default, Mar 22 2014, 22:59:56) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> import os
>>> os.getpid()
3196
>>> quit()
mmatczuk@cactus:~$ 

这是一个非常强大的工具,可用于:

  • 转储线程
  • 检查进程内存
  • 按需附加调试器,pydev debugger(同时适用于eclipse和pycharm)
  • 强制GC
  • 动态定义monkeypatch函数

甚至更多。在

下面是一个长期运行的程序示例,它还维护一个状态套接字。当客户端连接到套接字时,脚本会将一些状态信息写入套接字。在

#!/usr/bin/python

import os
import sys
import argparse
import random
import threading
import socket
import time
import select

val1 = 0
val2 = 0
lastupdate = 0
quit = False

# This function runs in a separate thread.  When a client connects,
# we write out some basic status information, close the client socket,
# and wait for the next connection.
def connection_handler(sock):
    global val1, val2, lastupdate, quit

    while not quit:
        # We use select() with a timeout here so that we are able to catch the
        # quit flag in a timely manner.
        rlist, wlist, xlist = select.select([sock],[],[], 0.5)
        if not rlist:
            continue

        client, clientaddr = sock.accept()
        client.send('%s %s %s\n' % (lastupdate, val1, val2))
        client.close()

# This function starts the listener thread.
def start_listener():
    sock = socket.socket(socket.AF_UNIX)

    try:
        os.unlink('/var/tmp/myprog.socket')
    except OSError:
        pass

    sock.bind('/var/tmp/myprog.socket')
    sock.listen(5)

    t = threading.Thread(
        target=connection_handler,
        args=(sock,))
    t.start()

def main():
    global val1, val2, lastupdate

    start_listener()

    # Here is the part of our script that actually does "work".
    while True:
        print 'updating...'
        lastupdate = time.time()
        val1 = val1 + random.randint(1,10)
        val2 = val2 + random.randint(100,200)
        print 'sleeping...'
        time.sleep(5)

if __name__ == '__main__':
    try:
        main()
    except (Exception,KeyboardInterrupt,SystemExit):
        quit=True
        raise

您可以编写一个简单的Python客户机来连接到套接字,也可以使用类似于socat的方法:

^{pr2}$

相关问题 更多 >