python обмен данными между скриптами
Как обмениваться переменными между скриптами в python?
выполняется в двух командных строках как:
(второй получает ошибку атрибута, правильно).
Есть ли способ выполнить это, то есть поделиться переменной между двумя скриптами?
ОТВЕТЫ
Ответ 1
Надеюсь, что это хорошо, чтобы записать мои заметки об этой проблеме.
Таким образом, большинство обращений относительно «общих переменных» и «межпроцессного общения» (IPC) обсуждают такие случаи, как эти два; однако в обоих случаях можно наблюдать «родителя», к которому «дети» обычно имеют ссылку.
Теперь, имея дело с этой проблемой в Perl, есть IPC::Shareable; который «позволяет привязать переменную к общей памяти», используя «целое число или 4 символьную строку [1], которая служит общим идентификатором для данных в пространстве процесса». Таким образом, нет временных файлов, а также сетевых настроек, которые я считаю отличными для моего варианта использования; поэтому я искал то же самое в Python.
Однако, как принятый ответ от @Drewfer отмечает: «Вы не сможете делать то, что хотите, не сохраняя информацию где-то внешнюю по отношению к двум экземпляры переводчика»; или другими словами: либо вы должны использовать настройку сети/сокета, либо вам нужно использовать временные файлы (ergo, нет общей RAM для «полностью отдельных сеансов python» ).
В дополнение ко всем ловушкам в записи «synchronize a python dict» в случае списка есть дополнительные. Это сообщение отмечает:
Все манипуляции с dict должны выполняться с помощью методов, а не диктовых назначений (syncdict [ «blast» ] = 2 терпит неудачу из-за того, что многопроцессорность делится пользовательскими объектами)
Другие связанные вопросы:
Ответ 2
Вы не сможете делать то, что хотите, не сохраняя информацию где-то внешнюю по отношению к двум экземплярам интерпретатора.
Если это просто простые переменные, которые вы хотите, вы можете легко сбрасывать питон python в файл с помощью модуля pickle в script one, а затем повторно загружать его в script два. Пример:
Ответ 3
sudo apt-get install memcached python-memcache
Ответ 4
То, что вы пытаетесь сделать здесь (сохранение общего состояния в модуле Python над отдельными интерпретаторами python), не будет работать.
Значение в модуле может быть обновлено одним модулем, а затем прочитано другим модулем, но это должно быть в пределах одного интерпретатора Python. То, что вы, кажется, делаете здесь, на самом деле своего рода межпроцессное общение; это может быть достигнуто через сокетную связь между двумя процессами, но это значительно менее тривиально, чем то, что вы ожидаете иметь здесь.
Ответ 5
Вы можете использовать относительный простой файл mmap. Вы можете использовать shared.py для хранения общих констант. Следующий код будет работать с разными интерпретаторами Python\scripts\process
* Этот код был написан для Windows, Linux может нуждаться в небольших корректировках
Ответ 6
Вам нужно сохранить переменную в каком-то постоянном файле. Для этого есть несколько модулей, в зависимости от вашей конкретной потребности.
Модуль pickle и cPickle может сохранять и загружать большинство объектов python в файл.
Модуль полки может хранить объекты python в словаре-подобной структуре (используя рассол за кулисами).
Модули dbm/bsddb/dbhash/gdm могут хранить строковые переменные в словаре-подобной структуре.
Модуль sqlite3 может хранить данные в легкой базе данных SQL.
Ответ 7
Я бы посоветовал вам использовать модуль multiprocessing. Вы не можете запускать два сценария из командной строки, но вы можете иметь два отдельных процесса, которые легко могут разговаривать друг с другом.
Из примеров документа:
Ответ 8
Используйте текстовые файлы или переменные среды. Поскольку эти два варианта выполняются отдельно, вы не можете делать то, что вы пытаетесь сделать.
Ответ 9
Ответ 10
Использование Redis для предоставления динамической переменной:
Учимся писать многопоточные и многопроцессные приложения на Python
Эта статья не для матёрых укротителей Python’а, для которых распутать этот клубок змей — детская забава, а скорее поверхностный обзор многопоточных возможностей для недавно подсевших на питон.
К сожалению по теме многопоточности в Python не так уж много материала на русском языке, а питонеры, которые ничего не слышали, например, про GIL, мне стали попадаться с завидной регулярностью. В этой статье я постараюсь описать самые основные возможности многопоточного питона, расскажу что же такое GIL и как с ним (или без него) жить и многое другое.
Python — очаровательный язык программирования. В нем прекрасно сочетается множество парадигм программирования. Большинство задач, с которыми может встретиться программист, решаются здесь легко, элегантно и лаконично. Но для всех этих задач зачастую достаточно однопоточного решения, а однопоточные программы обычно предсказуемы и легко поддаются отладке. Чего не скажешь о многопоточных и многопроцессных программах.
Многопоточные приложения
В Python есть модуль threading, и в нем есть все, что нужно для многопоточного программирования: тут есть и различного вида локи, и семафор, и механизм событий. Один словом — все, что нужно для подавляющего большинства многопоточных программ. Причем пользоваться всем этим инструментарием достаточно просто. Рассмотрим пример программы, которая запускает 2 потока. Один поток пишет десять “0”, другой — десять “1”, причем строго по-очереди.
Никакой магии и voodoo-кода. Код четкий и последовательный. Причем, как можно заметить, мы создали поток из функции. Для небольших задач это очень удобно. Этот код еще и достаточно гибкий. Допустим у нас появился 3-й процесс, который пишет “2”, тогда код будет выглядеть так:
Мы добавили новое событие, новый поток и слегка изменили параметры, с которыми
стартуют потоки (можно конечно написать и более общее решение с использованием, например, MapReduce, но это уже выходит за рамки этой статьи).
Как видим по-прежнему никакой магии. Все просто и понятно. Поехали дальше.
Global Interpreter Lock
Существуют две самые распространенные причины использовать потоки: во-первых, для увеличения эффективности использования многоядерной архитектуры cоврменных процессоров, а значит, и производительности программы;
во-вторых, если нам нужно разделить логику работы программы на параллельные полностью или частично асинхронные секции (например, иметь возможность пинговать несколько серверов одновременно).
В первом случае мы сталкиваемся с таким ограничением Python (а точнее основной его реализации CPython), как Global Interpreter Lock (или сокращенно GIL). Концепция GIL заключается в том, что в каждый момент времени только один поток может исполняться процессором. Это сделано для того, чтобы между потоками не было борьбы за отдельные переменные. Исполняемый поток получает доступ по всему окружению. Такая особенность реализации потоков в Python значительно упрощает работу с потоками и дает определенную потокобезопасность (thread safety).
Но тут есть тонкий момент: может показаться, что многопоточное приложение будет работать ровно столько же времени, сколько и однопоточное, делающее то же самое, или за сумму времени исполнения каждого потока на CPU. Но тут нас поджидает один неприятный эффект. Рассмотрим программу:
Эта программа просто пишет в файл миллион строк “1” и делает это за
0.35 секунды на моем компьютере.
Рассмотрим другую программу:
Эта программа создает 2 потока. В каждом потоке она пишет в отдельный файлик по пол миллиона строк “1”. По-сути объем работы такой же, как и у предыдущей программы. А вот со временем работы тут получается интересный эффект. Программа может работать от 0.7 секунды до аж 7 секунд. Почему же так происходит?
Это происходит из-за того, что когда поток не нуждается в ресурсе CPU — он освобождает GIL, а в этот момент его может попытаться получить и он сам, и другой поток, и еще и главный поток. При этом операционная система, зная, что ядер много, может усугубить все попыткой распределить потоки между ядрами.
UPD: на данный момент в Python 3.2 существует улучшенная реализация GIL, в которой эта проблема частично решается, в частности, за счет того, что каждый поток после потери управления ждет небольшой промежуток времени до того, как сможет опять захватить GIL (на эту тему есть хорошая презентация на английском)
«Выходит на Python нельзя писать эффективные многопоточные программы?», — спросите вы. Нет, конечно, выход есть и даже несколько.
Многопроцессные приложения
Для того, чтобы в некотором смысле решить проблему, описанную в предыдущем параграфе, в Python есть модуль subprocess. Мы можем написать программу, которую хотим исполнять в параллельном потоке (на самом деле уже процессе). И запускать ее в одном или нескольких потоках в другой программе. Такой способ действительно ускорил бы работу нашей программы, потому, что потоки, созданные в запускающей программе GIL не забирают, а только ждут завершения запущенного процесса. Однако, в этом способе есть масса проблем. Основная проблема заключается в том, что передавать данные между процессами становится трудно. Пришлось бы как-то сериализовать объекты, налаживать связь через PIPE или друге инструменты, а ведь все это несет неизбежно накладные расходы и код становится сложным для понимания.
Здесь нам может помочь другой подход. В Python есть модуль multiprocessing. По функциональности этот модуль напоминает threading. Например, процессы можно создавать точно так же из обычных функций. Методы работы с процессами почти все те же самые, что и для потоков из модуля threading. А вот для синхронизации процессов и обмена данными принято использовать другие инструменты. Речь идет об очередях (Queue) и каналах (Pipe). Впрочем, аналоги локов, событий и семафоров, которые были в threading, здесь тоже есть.
Кроме того в модуле multiprocessing есть механизм работы с общей памятью. Для этого в модуле есть классы переменной (Value) и массива (Array), которые можно “обобщать” (share) между процессами. Для удобства работы с общими переменными можно использовать классы-менеджеры (Manager). Они более гибкие и удобные в обращении, однако более медленные. Нельзя не отметить приятную возможность делать общими типы из модуля ctypes с помощью модуля multiprocessing.sharedctypes.
Еще в модуле multiprocessing есть механизм создания пулов процессов. Этот механизм очень удобно использовать для реализации шаблона Master-Worker или для реализации параллельного Map (который в некотором смысле является частным случаем Master-Worker).
Из основных проблем работы с модулем multiprocessing стоит отметить относительную платформозависимость этого модуля. Поскольку в разных ОС работа с процессами организована по-разному, то на код накладываются некоторые ограничения. Например, в ОС Windows нет механизма fork, поэтому точку разделения процессов надо оборачивать в:
Впрочем, эта конструкция и так является хорошим тоном.
Для написания параллельных приложений на Python существуют и другие библиотеки и подходы. Например, можно использовать Hadoop+Python или различные реализации MPI на Python (pyMPI, mpi4py). Можно даже использовать обертки существующих библиотек на С++ или Fortran. Здесь можно было упомянуть про такие фреймфорки/библиотеки, как Pyro, Twisted, Tornado и многие другие. Но это все уже выходит за пределы этой статьи.
Если мой стиль вам понравился, то в следующей статье постараюсь рассказать, как писать простые интерпретаторы на PLY и для чего их можно применять.
Сокеты в Python для начинающих
Предисловие
В далеком для меня 2010 году я писал статью для начинающих про сокеты в Python. Сейчас этот блог канул в небытие, но статья мне показалась довольно полезной. Статью нашел на флешке в либровском документе, так что это не кросспост, не копипаст — в интернете ее нигде нет.
Что это
Для начала нужно разобраться что такое вообще сокеты и зачем они нам нужны. Как говорит вики, сокет — это программный интерфейс для обеспечения информационного обмена между процессами. Но гораздо важнее не зазубрить определение, а понять суть. Поэтому я тут постараюсь рассказать все как можно подробнее и проще.
Существуют клиентские и серверные сокеты. Вполне легко догадаться что к чему. Серверный сокет прослушивает определенный порт, а клиентский подключается к серверу. После того, как было установлено соединение начинается обмен данными.
Рассмотрим это на простом примере. Представим себе большой зал с множеством небольших окошек, за которыми стоят девушки. Есть и пустые окна, за которыми никого нет. Те самые окна — это порты. Там, где стоит девушка — это открытый порт, за которым стоит какое-то приложение, которое его прослушивает. То есть, если, вы подойдете к окошку с номером 9090, то вас поприветствуют и спросят, чем могут помочь. Так же и с сокетами. Создается приложение, которое прослушивает свой порт. Когда клиент устанавливает соединение с сервером на этом порту именно данное приложение будет ответственно за работу этим клиентом. Вы же не подойдете к одному окошку, а кричать вам будут из соседнего 🙂
После успешной установки соединения сервер и клиент начинают обмениваться информацией. Например, сервер посылает приветствие и предложение ввести какую-либо команду. Клиент в свою очередь вводит команду, сервер ее анализирует, выполняет необходимые операции и отдает клиенту результат.
Сервер
Сейчас создайте два файла — один для сервера, а другой для клиента.
В Python для работы с сокетами используется модуль socket:
Прежде всего нам необходимо создать сокет:
Здесь ничего особенного нет и данная часть является общей и для клиентских и для серверных сокетов. Дальше мы будем писать код для сервера. Это вполне логично — зачем нам писать клиентское приложение, если некуда подключаться 🙂
Теперь нам нужно определиться с хостом и портом для нашего сервера. Насчет хоста — мы оставим строку пустой, чтобы наш сервер был доступен для всех интерфейсов. А порт возьмем любой от нуля до 65535. Следует отметить, что в большинстве операционных систем прослушивание портов с номерами 0 — 1023 требует особых привилегий. Я выбрал порт 9090. Теперь свяжем наш сокет с данными хостом и портом с помощью метода bind, которому передается кортеж, первый элемент (или нулевой, если считать от нуля) которого — хост, а второй — порт:
Теперь у нас все готово, чтобы принимать соединения. С помощью метода listen мы запустим для данного сокета режим прослушивания. Метод принимает один аргумент — максимальное количество подключений в очереди. Напряжем нашу бурную фантазию и вспомним про зал с окошками. Так вот этот параметр определяет размер очереди. Если он установлен в единицу, а кто-то, явно лишний, пытается еще подстроится сзади, то его пошлют 🙂 Установим его в единицу:
Ну вот, наконец-то, мы можем принять подключение с помощью метода accept, который возвращает кортеж с двумя элементами: новый сокет и адрес клиента. Именно этот сокет и будет использоваться для приема и посылке клиенту данных.
Вот и все. Теперь мы установили с клиентом связь и можем с ним «общаться». Т.к. мы не можем точно знать, что и в каких объемах клиент нам пошлет, то мы будем получать данные от него небольшими порциями. Чтобы получить данные нужно воспользоваться методом recv, который в качестве аргумента принимает количество байт для чтения. Мы будем читать порциями по 1024 байт (или 1 кб):
Как мы и говорили для общения с клиентом мы используем сокет, который получили в результате выполнения метода accept. Мы в бесконечном цикле принимаем 1024 байт данных с помощью метода recv. Если данных больше нет, то этот метод ничего не возвращает. Таким образом мы можем получать от клиента любое количество данных.
Дальше в нашем примере для наглядности мы что-то сделаем с полученными данными и отправим их обратно клиенту. Например, с помощью метода upper у строк вернем клиенту строку в верхнем регистре.
Теперь можно и закрыть соединение:
Собственно сервер готов. Он принимает соединение, принимает от клиента данные, возвращает их в виде строки в верхнем регистре и закрывает соединение. Все просто 🙂 В итоге у вас должно было получиться следующее:
Клиент
Думаю, что теперь будет легче. Да и само клиентское приложение проще — нам нужно создать сокет, подключиться к серверу послать ему данные, принять данные и закрыть соединение. Все это делается так:
Думаю, что все понятно, т.к. все уже разбиралось ранее. Единственное новое здесь — это метод connect, с помощью которого мы подключаемся к серверу. Дальше мы читаем 1024 байт данных и закрываем сокет.
Потоки. Передача файлов. Клиент-серверный чат¶
Потоки¶
На самом деле подпрограммы даже при использовании потоков не выполняются одновременно:
GIL переключает потоки по умолчанию раз в 5 миллисекунд, так что потоки работают не одновременно, а последовательно, постоянно сменяя друга.
Для работы с потоками используются модули _thread и threading (более новый).
Рассмотрим простой код для работы с потоками.:
Передача файлов¶
Настраиваем сокет, устанавливаем соединение.
На отправляющей стороне:
открываем файл на чтение в режиме байтового чтения ( ‘rb’ ).
построчно передаём файл принимающей стороне.
На принимающей стороне:
открываем файл на запись в режиме байтовой записи ( ‘wb’ ).
построчно пишем в файл всё, что получаем от передающей стороны.
Закрываем файлы и соединение.
Передача файлов байтовыми строками позволяет пересылать любые файлы, независимо от их типа, расширения и т.п.
Пример кода для отправки файла с клиента серверу.
Задания¶
Используя код из урока, реализуйте возможность отправлять файл с сервера клиенту.
Реализуйте возможность передачи файлов как от клиента серверу, так и от сервера клиенту:
оформите код с помощью функций;
добавьте графический интерфейс с помощью модуля easygui.
Используя потоки напишите клиент-серверный чат, который будет принимать и отправлять сообщения. Для этого потребуется оформить код в функции.
Взаимодействие процессов
Взаимосвязь процессов означает обмен данными между процессами. Для обмена параллельными приложениями необходимо обмениваться данными между процессами. Следующая диаграмма показывает различные механизмы связи для синхронизации между несколькими подпроцессами —
Различные коммуникационные механизмы
В этом разделе мы узнаем о различных коммуникационных механизмах. Механизмы описаны ниже —
Очереди
пример
Ниже приведен простой пример, взятый из официальных документов Python по многопроцессорности, для понимания концепции многопроцессорного класса Queue.
Выход
трубы
Это структура данных, которая используется для связи между процессами в многопроцессорных программах. Функция Pipe () возвращает пару объектов соединения, соединенных каналом, который по умолчанию является дуплексным (двухсторонним). Это работает следующим образом —
Он возвращает пару объектов соединения, которые представляют два конца канала.
У каждого объекта есть два метода — send () и recv () для взаимодействия между процессами.
Он возвращает пару объектов соединения, которые представляют два конца канала.
У каждого объекта есть два метода — send () и recv () для взаимодействия между процессами.
пример
Выход
Менеджер
Менеджер — это класс многопроцессорных модулей, который обеспечивает способ координации общей информации между всеми его пользователями. Управляющий объект управляет процессом сервера, который управляет общими объектами и позволяет другим процессам манипулировать ими. Другими словами, менеджеры предоставляют способ создавать данные, которые могут быть разделены между различными процессами. Ниже приведены различные свойства объекта менеджера —
Основным свойством менеджера является управление серверным процессом, который управляет общими объектами.
Другим важным свойством является обновление всех общих объектов, когда какой-либо процесс изменяет их.
Основным свойством менеджера является управление серверным процессом, который управляет общими объектами.