2014-06-18 8 views
5

के साथ बातचीत करना मेरे पास एक लंबी चल रही पायथन लिपि है जो ट्विटर से ट्वीट एकत्र करती है, और मैं जानना चाहता हूं कि यह थोड़ी देर में हर बार कैसे कर रहा है।लंबे समय से चलने वाले पायथन स्क्रिप्ट

वर्तमान में, मैं इंटरप्ट्स को पकड़ने के लिए signal लाइब्रेरी का उपयोग कर रहा हूं, जिस बिंदु पर मैं अपना प्रिंट फ़ंक्शन कॉल करता हूं। कुछ इस तरह:

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)) 

और जब भी मैं अपने जानकारी चाहते हैं, तो मैं एक नया टर्मिनल खोलने और मेरी व्यवधान जारी करते हैं:

$kill -USR1 <pid> 

वहाँ यह करने के लिए एक बेहतर तरीका है? मुझे पता है कि मेरी निर्धारित स्क्रिप्ट पर मेरी स्क्रिप्ट कुछ हो सकती है, लेकिन मुझे मांग पर जानने में और अधिक संभावनाएं जारी करने में अधिक रुचि है।

+0

यह एक लागू उपयोग सिग्नल लाइब्रेरी प्रतीत होता है। आपको क्यों लगता है कि एक बेहतर तरीका है? – MrAlias

+0

आप कनेक्शन के लिए सॉकेट पर थ्रेड सुन सकते हैं और फिर क्लाइंट कनेक्ट होने पर सॉकेट को जानकारी लिख सकते हैं। – larsks

+0

@MrAlias ​​मैं एक से अधिक "प्रिंट" विधि रखने की योजना बना रहा हूं, और जो मैं कह सकता हूं उससे इंटरप्ट का एक सीमित हिस्सा है जिसका उपयोग मैं कर सकता हूं, इसलिए मैंने सोचा कि शायद रनटाइम के दौरान मेरे प्रोग्राम से बातचीत करने का एक अलग तरीका था। – Tyler

उत्तर

0

मैं व्यक्तिगत रूप से एक फ़ाइल को जानकारी लिखता हूं ताकि मेरे पास बाद में हो, हालांकि इसका शायद थोड़ा धीमा होने का नुकसान है क्योंकि इसे हर बार फ़ाइल में लिखना पड़ता है या हर बार यह एक ट्वीट को पुनर्प्राप्त करता है।

फिर भी, यदि आप इसे एक फ़ाइल "output.txt" को लिखते हैं, आप ऊपर bash और किसी भी प्रकार tail output.txt में नवीनतम 10 फ़ाइल में मुद्रित लाइनों के लिए खोल सकते हैं, या आप tail -f output.txt, जो लगातार लाइनों के साथ टर्मिनल शीघ्र अद्यतन करता टाइप कर सकते हैं कि आप फाइल को लिख रहे हैं। अगर आप रुकना चाहते हैं, तो बस Ctrl-C

0

यहां एक उदाहरण है जो लंबे समय से चलने वाला प्रोग्राम है जो एक स्थिति सॉकेट भी बनाए रखता है। जब कोई ग्राहक सॉकेट से कनेक्ट होता है, तो स्क्रिप्ट सॉकेट को कुछ स्थिति जानकारी लिखती है।

#!/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 

आप सॉकेट से कनेक्ट करने के लिए एक सरल अजगर ग्राहक लिख सकता है, या आप socat की तरह कुछ इस्तेमाल कर सकते हैं:

$ socat - unix:/var/tmp/myprog.sock 
1403061693.06 6 152 
0

मैं इससे पहले इसी तरह की एक आवेदन में लिखें।

यहाँ मैं क्या किया है:

केवल कुछ की जरूरत आदेशों देखते हैं जब, के रूप में तुमने किया था मैं सिर्फ संकेत का उपयोग करें, सिर्फ यह बहुत जटिल नहीं बनाने के लिए। कमांड द्वारा, मेरा मतलब है कि आप चाहते हैं कि आप अपनी पोस्ट में print_info जैसे आवेदन करें।

लेकिन जब एप्लिकेशन अपडेट किया गया, तो कई अलग-अलग कमांड की आवश्यकता होती है, मैंने सॉकेट पोर्ट पर सुनकर एक विशेष धागा का उपयोग करना शुरू किया या कमांड स्वीकार करने के लिए स्थानीय फाइल पढ़ना शुरू किया। मान लीजिए आवेदन print_info1 (या बस लिखने print_info1 एक स्थानीय फाइल करने के लिए ताकि आप लक्ष्य पोर्ट से कनेक्ट एक ग्राहक का उपयोग करें और लिख सकते हैं print_info1 आवेदन निष्पादित आदेश बनाने के लिए, prinf_info1print_info2print_info3 समर्थन करने की आवश्यकता है, तो आप उपयोग कर रहे स्थानीय फाइल तंत्र पढ़ने)।

सॉकेट पोर्ट तंत्र पर सुनने का उपयोग करते समय, नुकसान यह है कि आदेश देने के लिए ग्राहक को लिखने के लिए थोड़ा और काम लगेगा, लाभ यह है कि आप कहीं भी ऑर्डर दे सकते हैं।

स्थानीय फ़ाइल तंत्र को पढ़ने का उपयोग करते समय, नुकसान यह है कि आपको थ्रेड को फ़ाइल को लूप में जांचना होगा और यह थोड़ा संसाधन का उपयोग करेगा, लाभ ऑर्डर देना बहुत आसान है (बस एक स्ट्रिंग लिखें एक फ़ाइल) और आपको क्लाइंट और सॉकेट सुनो सर्वर लिखने की आवश्यकता नहीं है।

1

प्रक्रिया के लिए संकेत भेजना प्रक्रिया को बाधित करेगा। नीचे आपको पाइथन कंसोल अनुकरण करने के लिए समर्पित थ्रेड का उपयोग करने वाला एक दृष्टिकोण मिलेगा। कंसोल को यूनिक्स सॉकेट के रूप में उजागर किया जाता है।

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 

उदाहरण कार्यक्रम:

make_threaded_backdoor(prefix='test') 
while True: 
    pass 

उदाहरण सत्र:

[email protected]:~$ 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() 
[email protected]:~$ 

यह एक बहुत मज़बूत उपकरण जो करने के लिए इस्तेमाल किया जा सकता है:

  • डंप सूत्र,
  • प्रक्रिया स्मृति का निरीक्षण किया,
  • मांग पर डीबगर देते हैं, pydev debugger (दोनों ग्रहण और pycharm के लिए काम करते),
  • बल जीसी, मक्खी

और भी अधिक पर

  • monkeypatch समारोह परिभाषा।

  • 0

    rpyc इस कार्य के लिए एकदम सही उपकरण है।

    संक्षेप में, आप rpyc.Service कक्षा को परिभाषित करते हैं जो आपके द्वारा खुलासा करने वाले आदेशों का खुलासा करता है, और rpyc.Server धागा शुरू करता है।

    आपका ग्राहक तब आपकी प्रक्रिया से जुड़ता है, और आपके सेवा के आदेशों के लिए मैप किए गए तरीकों को कॉल करता है।

    यह उतना आसान और साफ है जितना। सॉकेट, सिग्नल, ऑब्जेक्ट सीरियलाइजेशन के बारे में चिंता करने की ज़रूरत नहीं है।

    इसमें अन्य अच्छी सुविधाएं भी हैं, उदाहरण के लिए प्रोटोकॉल सममित है।

    0

    आपका प्रश्न इंटरप्रोसेस संचार से संबंधित है। आप एक साझा स्मृति का उपयोग करके, या एक संदेश कतार या कैश सिस्टम जैसे RabbitMQ और Redis का उपयोग करके यूनिक्स सॉकेट या टीसीपी पोर्ट पर संचार करके इसे प्राप्त कर सकते हैं।

    This post साझा स्मृति इंटरप्रोसेस संचार प्राप्त करने के लिए mmap का उपयोग करने के बारे में वार्ता।

    यहां redis और RabbitMQ के साथ शुरू करने का तरीका बताया गया है, दोनों लागू करने के लिए सरल हैं।

    संबंधित मुद्दे