Постоянно работающий скрипт Python, вызывающий функции через терминал - PullRequest
0 голосов
/ 11 июля 2011

быстрый вопрос, в котором я даже не уверен: 3

У меня есть сценарий python, сетевой сценарий, который подключается к серверу и остается подключенным до тех пор, пока я либо не отключу его, либо он пинает меня (чего обычно не следует), который постоянно получает данные и выполняет другие задачи.

Мне было любопытно, возможно ли вообще во время работы скрипта запускать функции из скрипта? Скажем, во время работы скрипта, если бы у меня было желание отправить какие-то данные на сервер, я мог бы напечатать их и отправить в функцию, которая их обрабатывает?

Не был уверен, возможно ли это или нет, так как мне никогда не приходилось пытаться или даже не видел, чтобы это было сделано. Если это поможет, я на Ubuntu Linux запускаю скрипт из терминала.

Ответы [ 5 ]

1 голос
/ 11 июля 2011

Решение Яцека Конечного хорошее и простое. Если вы хотите более гибкую передачу сообщений, рассмотрите ZeroMQ . Это дает вам много возможностей для простого создания различных решений для обмена сообщениями вокруг вашей основной программы. Используя один поток, ваша основная программа будет выглядеть примерно так:

#!/usr/bin/env python

import zmq
from time import sleep

CTX = zmq.Context()

incoming = CTX.socket(zmq.PULL)
incoming.bind("tcp://127.0.0.1:3000")

outgoing = CTX.socket(zmq.PUB)
outgoing.bind("tcp://127.0.0.1:3001")

# Poller for the incoming messages
poller = zmq.Poller()
poller.register(incoming, zmq.POLLIN)

def main():
    while True:
        # Do things on the network
        print("[Did things on the network]")
        # Send messages if you want
        outgoing.send("Important message")
        # Poll for incoming messages
        socks = dict(poller.poll(zmq.NOBLOCK))
        if incoming in socks and socks[incoming] == zmq.POLLIN:
            message = incoming.recv()
            # Handle message
            print("[Handled message '%s']" % message)

        sleep(1) # Only for this dummy program

if __name__ == "__main__":
    main()

Затем вы должны написать клиента (на любом языке с привязками ZeroMQ), который отправляет и подписывается на сообщения из основной программы. Пример толкателя:

#!/usr/bin/env python

import zmq

CTX = zmq.Context()

pusher = CTX.socket(zmq.PUSH)
pusher.connect("tcp://127.0.0.1:3000")

def main():
    pusher.send("Message to main program")

if __name__ == "__main__":
    main()

Пример подписчика:

#!/usr/bin/env python

import zmq

CTX = zmq.Context()

subscriber = CTX.socket(zmq.SUB)
subscriber.connect("tcp://127.0.0.1:3001")
subscriber.setsockopt(zmq.SUBSCRIBE, "")

def main():
    while True:
        msg = subscriber.recv()
        print("[Received message] %s" % msg)

if __name__ == "__main__":
    main()

Звучит так, как будто вы захотите объединить программы подписчика и подписчика в одну. Если вы решили использовать ZeroMQ, взгляните на отличное руководство пользователя .

Конечно, вы также можете использовать ZeroMQ с несколькими потоками или процессами (только будьте осторожны, чтобы не разделять отдельные сокеты ZeroMQ между потоками).

1 голос
/ 11 июля 2011

Взгляните на gevent :

gevent - сетевая библиотека Python на основе сопрограмм, которая использует greenlet для предоставления высокоуровневого синхронного API поверх события libeventloop.

и gevent.socket .

1 голос
/ 11 июля 2011

Обычный способ UNIX для решения таких проблем - опрос или выбор как для сокета, так и для стандартных дескрипторов входного файла. Затем вы обрабатываете сетевой вход по событию IN на сокете и терминальный вход по событию IN в дескрипторе файла stdin.

Это не переносимо в Windows (что плохо), но это наиболее естественный способ сделать это в UNIX-подобных системах. И вы не получите всех проблем, связанных с потоками (которые часто требуют опроса в Python, так как в противном случае они становятся «неубиваемыми»).

0 голосов
/ 11 июля 2011

Вставьте свой сервер в другой поток (исследуйте модуль threading) и используйте основной поток для взаимодействия с пользователем через raw_input / input.

0 голосов
/ 11 июля 2011

Без подробностей я могу предоставить вам только общие идеи.Для одновременного выполнения двух действий (загрузка с сервера и ожидание отправки данных) вам потребуется использовать несколько потоков или процессов.Здесь есть учебник с примерами нескольких потоков здесь .Если вы используете несколько процессов, вы будете использовать пакет multiprocessing .

При любом решении вам потребуется аналогичная настройка.В остальном я буду использовать термин поток, но вы можете легко заменить его на процесс, если вместо этого вы используете несколько процессов.Вероятно, у вас есть (по крайней мере) поток для отправки и получения данных (это может быть два потока) и отдельный поток для ожидания чего-либо для отправки.Это упрощенный пример проблемы производителя / потребителя .Поток, который ожидает команды / данные, будет простым циклом ввода, который создает данных для отправки, в то время как поток, который отправляет данные, будет потреблять данных при отправке их на сервер..

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...