Ce qui suit ne fonctionne pas
one.py
import shared
shared.value = 'Hello'
raw_input('A cheap way to keep process alive..')
deux.pypy
import shared
print shared.value
exécuter sur deux lignes de commande comme suit:
>>python one.py
>>python two.py
(La seconde obtient une erreur d'attribut, à juste titre).
Existe-t-il un moyen d'accomplir cela, c'est-à-dire partager une variable entre deux scripts?
Sudo apt-get install memcached python-memcache
one.py
import memcache
shared = memcache.Client(['127.0.0.1:11211'], debug=0)
shared.set('Value', 'Hello')
deux.pypy
import memcache
shared = memcache.Client(['127.0.0.1:11211'], debug=0)
print shared.get('Value')
Ce que vous essayez de faire ici (stockez un état partagé dans un Python module sur séparé python interprètes) ne fonctionnera pas.
Une valeur dans un module peut être mise à jour par un module, puis lue par un autre module, mais cela doit être dans le même fichier Python INTERPRÈTE. Qu'est-ce que vous semblez faire ici est en fait une sorte d'interprocession Communication; cela pourrait être accompli via une communication de socket entre les deux processus, mais il est significativement moins trivial que ce que vous attendez de travailler ici.
vous pouvez utiliser le fichier MMAP simple relativement. Vous pouvez utiliser le Shared.py pour stocker les constantes communes. Le code suivant fonctionnera sur différents python interprètes\scripts\processus
partagé.py:
MMAP_SIZE = 16*1024
MMAP_NAME = 'Global\\SHARED_MMAP_NAME'
* Le "global" est la syntaxe Windows pour les noms mondiaux
one.py:
from shared import MMAP_SIZE,MMAP_NAME
def write_to_mmap():
map_file = mmap.mmap(-1,MMAP_SIZE,tagname=MMAP_NAME,access=mmap.ACCESS_WRITE)
map_file.seek(0)
map_file.write('hello\n')
ret = map_file.flush() != 0
if sys.platform.startswith('win'):
assert(ret != 0)
else:
assert(ret == 0)
deux.py:
from shared import MMAP_SIZE,MMAP_NAME
def read_from_mmap():
map_file = mmap.mmap(-1,MMAP_SIZE,tagname=MMAP_NAME,access=mmap.ACCESS_READ)
map_file.seek(0)
data = map_file.readline().rstrip('\n')
map_file.close()
print data
* Ce code a été écrit pour Windows, Linux peut avoir besoin de petits ajustements
plus d'infos à - https://docs.python.org/2/library/mmap.html
Je vous conseillerais d'utiliser le module multiprocessing . Vous ne pouvez pas exécuter deux scripts de la ligne de commande, mais vous pouvez avoir deux processus distincts se parler facilement.
Des exemples du doc:
from multiprocessing import Process, Queue
def f(q):
q.put([42, None, 'hello'])
if __name__ == '__main__':
q = Queue()
p = Process(target=f, args=(q,))
p.start()
print q.get() # prints "[42, None, 'hello']"
p.join()
Vous devez stocker la variable dans une sorte de fichier persistant. Il existe plusieurs modules pour le faire, en fonction de votre besoin exact.
Le module cornichon et cpickle peut enregistrer et charger la plupart python objets à fichier.
Le module d'étagère peut stocker python objets dans une structure en forme de dictionnaire (en utilisant le cornichement dans les coulisses).
Les modules DBM/BSDDB/DBHASH/GDM peuvent stocker des variables de chaîne dans une structure de type dictionnaire.
Le module SQLITE3 peut stocker des données dans une base de données SQL légère.
Le plus gros problème de la plupart d'entre eux est qu'ils ne sont pas synchronisés sur différents processus - si un processus lit une valeur tandis qu'un autre écrit dans le magasin de données, vous pouvez obtenir des données incorrectes ou une corruption de données. Pour vous rond, vous devrez écrire votre propre mécanisme de verrouillage de fichiers ou utiliser une base de données complète.
Utilisez des fichiers texte ou des variables d'environnement. Depuis les deux coureurs séparément, vous ne pouvez pas vraiment faire ce que vous essayez de faire.
Dans votre exemple, le premier script passe à l'achèvement, puis le deuxième script fonctionne. Cela signifie que vous avez besoin d'une sorte d'état persistant. D'autres réponses ont suggéré d'utiliser des fichiers texte ou du module de pickle
de Python. Personnellement, je suis paresseux, et je n'utiliserais pas de fichier texte lorsque je pourrais utiliser pickle
; Pourquoi devrais-je écrire un analyseur pour analyser mon propre format de fichier texte?
Au lieu de pickle
, vous pouvez également utiliser le module json
pour la stocker en tant que JSON. Cela pourrait être préférable si vous souhaitez partager les données aux programmes non python, car JSON est une norme simple et commune. Si votre Python n'a pas json
, obtenez-vous SimpleJson .
Si vos besoins vont au-delà de pickle
ou json
- dites que vous voulez réellement avoir deux Python programmes exécutant en même temps et mettre à jour les variables d'état persistantes dans Temps réel - Je vous suggère d'utiliser la base de données SQLite . Utilisez un orj pour résumer la base de données, et c'est super facile. Pour SQLite et Python, je recommande automne orm .
Redis
pour partager une variable dynamique:from redis import Redis
from time import sleep
cli = Redis('localhost')
shared_var = 1
while True:
cli.set('share_place', shared_var)
shared_var += 1
sleep(1)
$ python script_one.py
from time import sleep
from redis import Redis
cli = Redis('localhost')
while True:
print(int(cli.get('share_place')))
sleep(1)
$ python script_two.py
Dehors:
1
2
3
4
5
...
$ pip install redis
$ apt-get install redis-server
Vous pouvez également résoudre ce problème en faisant la variable comme mondiale.
python first.pypy
class Temp:
def __init__(self):
self.first = None
global var1
var1 = Temp()
var1.first = 1
print(var1.first)
python second.pypy
import first as One
print(One.var1.first)
Si vous voulez lire et modifier des données partagées entre 2 scripts qui fonctionnent séparément, une bonne solution serait de tirer parti du module multiprocession python et Utilisez A Tuyau () ou une file d'attente () (voir Différences ICI ). De cette façon, vous obtenez des scripts synchronisés et évitez les problèmes concernant la concurrence et les variables globales (comme ce qui se passe si les deux scripts veulent modifier une variable en même temps).
La meilleure partie de l'utilisation de tuyaux/files d'attente est que vous pouvez passer des objets python à travers eux.
Il existe également des méthodes pour éviter d'attendre des données s'il n'y a pas encore été passé ( file d'attente.empty () et Pipeconn.poll () )] ==).
Voir un exemple d'utilisation de la file d'attente () ci-dessous:
# main.py
from multiprocessing import Process, Queue
from stage1 import Stage1
from stage2 import Stage2
s1= Stage1()
s2= Stage2()
# S1 to S2 communication
queueS1 = Queue() # s1.stage1() writes to queueS1
# S2 to S1 communication
queueS2 = Queue() # s2.stage2() writes to queueS2
# start s2 as another process
s2 = Process(target=s2.stage2, args=(queueS1, queueS2))
s2.daemon = True
s2.start() # Launch the stage2 process
s1.stage1(queueS1, queueS2) # start sending stuff from s1 to s2
s2.join() # wait till s2 daemon finishes
# stage1.py
import time
import random
class Stage1:
def stage1(self, queueS1, queueS2):
print("stage1")
lala = []
lis = [1, 2, 3, 4, 5]
for i in range(len(lis)):
# to avoid unnecessary waiting
if not queueS2.empty():
msg = queueS2.get() # get msg from s2
print("! ! ! stage1 RECEIVED from s2:", msg)
lala = [6, 7, 8] # now that a msg was received, further msgs will be different
time.sleep(1) # work
random.shuffle(lis)
queueS1.put(lis + lala)
queueS1.put('s1 is DONE')
# stage2.py
import time
class Stage2:
def stage2(self, queueS1, queueS2):
print("stage2")
while True:
msg = queueS1.get() # wait till there is a msg from s1
print("- - - stage2 RECEIVED from s1:", msg)
if msg == 's1 is DONE ':
break # ends loop
time.sleep(1) # work
queueS2.put("update lists")
[~ # ~ ~] Edit [~ # ~] : vient de trouver que vous pouvez utiliser Queue.get (False) = pour éviter le blocage lors de la réception de données. De cette façon, il n'est pas nécessaire de vérifier d'abord si la file d'attente est vide. Cela n'est pas possible si vous utilisez des tuyaux.