Encoding issues (i think) when reading serial interface - python

I am trying to read out my smart meter through a P1 interface.
Some python scripts are posted on the web to do so, and I tried them, but seem to be getting some partial garbage out of my serial interface (not completely - so my assumption is that the serial settings are correct though. Also since I am copying this from other scripts that seem to be working).
When trying to readout the interface using cu command it does show the right output, so my hardware seems to work.
I am running this on: Linux version 3.10.25+ (dc4#dc4-arm-01) (gcc version 4.7.2 20120731 (prerelease) (crosstool-NG linaro-1.13.1+bzr2458 - Linaro GCC 2012.08) ) #622 PREEMPT Fri Jan 3 18:41:00 GMT 2014
Here is what the output should look like - retrieved through:
command:
cu -l /dev/ttyUSB0 -s 9600 --parity=none
output
/INTENTIONALLY ALTERED
0-0:96.1.1(39373936353532302020202020202020)
1-0:1.8.1(05090.742*kWh)
1-0:1.8.2(06618.743*kWh)
1-0:2.8.1(00000.000*kWh)
1-0:2.8.2(00000.000*kWh)
0-0:96.14.0(0001)
1-0:1.7.0(0000.71*kW)
1-0:2.7.0(0000.00*kW)
0-0:17.0.0(999*A)
0-0:96.3.10(1)
0-0:96.13.1()
0-0:96.13.0()
0-1:96.1.0(3238303131303038323033333632313132)
0-1:24.1.0(03)
0-1:24.3.0(140806220000)(2C)(60)(1)(0-1:24.2.0)(m3)
(03447.404)
0-1:24.4.0(1)
!
When I use the following Python code:
# DSMR P1 uitlezen
# (c) 10-2012 - GJ - gratis te kopieren en te plakken
versie = "1.0"
import sys
import serial
##############################################################################
#Main program
##############################################################################
print ("DSMR P1 uitlezen", versie)
print ("Control-C om te stoppen")
print ("Pas eventueel de waarde ser.port aan in het python script")
#Set COM port config
ser = serial.Serial()
ser.baudrate = 9600
ser.bytesize=serial.SEVENBITS
ser.parity=serial.PARITY_EVEN
ser.stopbits=serial.STOPBITS_ONE
ser.xonxoff=0
ser.rtscts=0
ser.timeout=20
ser.port="/dev/ttyUSB0"
#Open COM port
try:
ser.open()
except:
sys.exit ("Fout bij het openen van %s. Aaaaarch." % ser.name)
#Initialize
#p1_teller is mijn tellertje voor van 0 tot 20 te tellen
p1_teller=0
while p1_teller < 20:
p1_line=''
#Read 1 line van de seriele poort
try:
p1_raw = ser.readline()
print str(p1_teller),':', p1_raw
except:
sys.exit ("Seriele poort %s kan niet gelezen worden. Aaaaaaaaarch." % ser.name )
#p1_str=str(p1_raw)
#p1_line=p1_str.strip()
# als je alles wil zien moet je de volgende line uncommenten
#print (p1_line.encode('ascii','ignore'))
p1_teller = p1_teller +1
#Close port and show status
try:
ser.close()
except:
sys.exit ("Oops %s. Programma afgebroken. Kon de seriele poort niet sluiten." % ser.name )
The output turns into this:
('DSMR P1 uitlezen', '1.0')
Control-C om te stoppen
Pas eventueel de waarde ser.port aan in het python script
0 : INTENTIONALLY ALTERED BUT ALSO WITH THE ? SYMBOLS IN THE ORIGINAL OUTPUT
1 : �
2 : 0-0:96.�.�(393�393635353�30�0�0�0�0�0�0�0�0��
3 : �-0:�.�.�(05090.�9����詍
4 : �-0:�.�.�(066��.��3���詍
5 : �-0:�.�.�(00000.000���詍
6 : �-0:�.�.�(00000.000���詍
7 : 0-0:96.��.0(000���
8 : �-0:�.�.0(0000.�0��ש�
9 : �-0:�.�.0(0000.00��ש�
10 : 0-0:��.0.0(999�A��
11 : 0-0:96.3.�0(���
12 : 0-0:96.�3.�(��
13 : 0-0:96.�3.0(��
14 : 0-�:96.�.0(3�3�303�3�30303�3�303333363�3�3�3���
15 : 0-�:��.�.0(03��
16 : 0-�:��.3.0(��0�06��0000�(�é(60�(��(0-�:��.�.0�(�3��
17 : (03���.�0���
18 : 0-�:��.�.0(���
19 : !�
so there are a lot of � characters in my python output, that I expect to be some encoding issue.. but not sure and not sure how to fix this... so any help is appreciated.

It looks like the bytes you read may still contain the parity bit, making them invalid characters. Try this to remove the 8th bit:
p1_raw = ''.join(chr(ord(ch) & 0x7f) for ch in p1_raw)

This is how I in the end fixed it - Will try Ldevries method too.... looks pretty clean:
#
# MBSolget P1 Telegram Catch
#
version = "v1.00"
import sys
import os
import stat
import serial
import datetime
import locale
###############################################################################################################
# Main program
###############################################################################################################
#Initialize
p1_telegram = False
p1_timestamp = ""
p1_teller = 0
p1_log = True
#Set COM port config
ser = serial.Serial()
ser.baudrate = 9600
ser.bytesize = serial.EIGHTBITS
ser.parity = serial.PARITY_NONE
ser.stopbits = serial.STOPBITS_ONE
ser.xonxoff = 1
ser.rtscts = 0
ser.timeout = 30
ser.port = "/dev/ttyUSB0"
#Show startup arguments
print ("MBSolget P1 Telegram Catch %s" % version)
print ("Control-C om af te breken")
print ("Poort: (%s)" % (ser.name) )
#Open COM port
try:
ser.open()
except:
sys.exit ("Fout bij het openen van poort %s. " % ser.name)
while p1_log:
p1_line = ''
try:
p1_raw = ser.readline()
except:
sys.exit ("Fout bij het lezen van poort %s. " % ser.name )
ser.close()
p1_raw = ''.join(chr(ch & 0x7f) for ch in p1_raw)
# for ch in p1_raw:
# print(chr(ch & 0x7f))
# print( chr(ord(ch) & 0x7f))
# print(p1_raw)
p1_str = p1_raw #str(p1_raw ,"utf-8",errors="ignore")
p1_line = p1_str.strip()
print (p1_line)
if p1_line[0:1] == "/":
p1_telegram = True
p1_teller = p1_teller + 1
f=open("/home/geoffrey/p1_temp.log", "w")
elif p1_line[0:1] == "!":
if p1_telegram:
p1_teller = 0
p1_telegram = False
p1_log = False
f.write (p1_line)
f.write ('\r\n')
f.close()
os.chmod("/home/geoffrey/p1_temp.log", stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)
if p1_telegram:
f.write (p1_line)
f.write ('\r\n')
#Close port and show status
try:
ser.close()
except:
sys.exit ("Fout bij het sluiten van %s. Programma afgebroken." % ser.name )

I guess it has to do with some decoding of data. Using textIOWrapper the decoding works fine for me. Hopefully you can do anything with my view on the case:
To make the readout of the p1 protocol as easy as possible I'd suggest to use TextIOWrapper as I mentioned before, this way you can still read the serial port with the readline method. The "!" always ends the P1 telegram, so that can be used to detect the end of the message instead of using a counter. When a full telegram has been received, the telegram can be processed. Example:
import io
import serial
serialport = serial.Serial( # Configure Serial communication port
port = "/dev/ttyUSB0"
baudrate = 9600,
timeout = 11,
bytesize = serial.SEVENBITS,
parity = serial.PARITY_EVEN,
stopbits = serial.STOPBITS_ONE )
p1port = io.TextIOWrapper(io.BufferedReader(serialport, buffer_size=1), newline='\n', encoding='ascii')
P1Message = []
while True:
try:
rawline = p1port.readline()
except UnicodeDecodeError:
print "Encode error on readline"
if '!' in rawline:
# Process your P1Message here
P1Message = [] # Clear message, wait for new one
else:
P1Message.append(rawline)
Good luck!

In the code, change the byte size to EIGHTBITS and parity to PARITY_NONE. Those match what cu is using (and are also the defaults for PySerial).

Thanks to Geoffrey I finally figured out how to setup my C# SerialPort.
private static SerialPort CreateP1SerialPort(string name)
{
return new SerialPort
{
BaudRate = 115200,
DataBits = 8,
Handshake = Handshake.XOnXOff,
Parity = Parity.None,
PortName = name,
RtsEnable = false,
StopBits = StopBits.One,
ReadTimeout = 10 * 1000,
WriteTimeout = 1000
};
}
simple example:
public static void Main()
{
// this will help you find your com port name
var portNames = SerialPort.GetPortNames().OrderBy(x => x).ToArray();
// Create a new SerialPort object with default settings.
var serialPort = CreateP1SerialPort("COM7");
serialPort.Open();
while (true)
{
var line = serialPort.ReadExisting();
if (string.IsNullOrEmpty(line))
{
Thread.Sleep(10000); // one message every 10 seconds
} else
Console.WriteLine(line);
}
}

Related

convert a tuple of tuples into bytes in python

I'm making a video game in upbge (which for this aspect is basically python) but to send the info between sockets it needs to be in bytes but i only found a way to do it turning it into a string, (because the list get's created with the game (i have a script that once a new entity appears it get's added to the list in the form of (Player-entity|data) but i want the data to variate between entities and i ran out of symbols to use to split it into lists so i'm trying to send the data as a list to be able to simply check it's components, but as it's a list inside of a list (and sometimes more) the bytearray won't work (at least i can't figure out how to make it work)
I'm unsure of how to summarize the code, but this is the code that I have now to generate that info
import socket
mi_socket = socket.socket()
mi_socket.bind(('127.0.0.1',55555))
mi_socket.listen()
TP = 0 #Total players
AP = 0 #Actual player
PL = ["host"] #Player List
AE = 0 #Actual entity
TE = 0 #Total entities
EL = ["|PlayerEntity$[Data]|"] #Entity list
PI = [] #Player Intel (Player name, Total Players, Player Code) (apartado uno en las comunicaciones)
order = None #Variable reservada para guardar comandos u identificaciones (ej: nombre de la entidad) en las comunicaciones
content = None #Variable reservada para almacenar la información recibida
incoming = 0 #Variable reservada para analizar el mensaje recibido de entrada
def login():
global AP
global TP
global PL
PJ = str(incoming).split("$")[1] #incoming Player
if AP <= TP:
if PJ!=str(PL[int(AP)]): #Nombre jugador que se conecta
AP+=1
login()
pass
else:
identity()
pass
if AP > TP:
PL.append(str("Player" + str(AP))) #Agregar jugador a la lista
TP = int(AP)
def identity(): #identifica de qué se trata la orden para responder en consecuencia, si se trata de entidad anota tmb la entidad en la lista
global TE
global AE
global EL
global AP
global PL
PJ = str(incoming).split("$")[1] # incoming Player
PE = str(incoming).split("$")[2] # incoming entity
if AE <= TE:
# Si nombre de jugador|nombre de objeto no és EL[AE]([1]|[2])
if str(str(PL[AP])+"-"+str(PE)) != str(str(EL[AE]).split("|")[1]).split("$")[0]:
AE+=1
identity()
pass
else:
EL[AE] = "|"+PL[AP]+"-"+PE+"$"+str(incoming).split("$")[3]+"|"
if AE > TE:
EL.append("|"+PL[AP]+"-"+PE+"$"+str(incoming).split("$")[3]+"|")
TE = int(AE)
def main():
global AP
global AE
global TE
global incoming
conexion, ip = mi_socket.accept()
incoming = conexion.recv(1024)
login()
conexion.send(str("#"+str(PL[AP])+"#"+str(EL[1:TE+1])+"#").encode())
AP=0
AE=0
conexion.close()
while True:
main()

When using win32print + cx_Freeze, print instruction doesn't work without producing any error

Windows 10 (x64)
Python 3.6.3
cx_Freeze 5.1.1
pypiwin32 223 / pywin32 224
I made a module for printing, the module works fine when launching it as a script.
Once passed through cx_Freeze, the print command doesn't work without producing any error message.
Here is my setup.py for creating builds (by: python setup.py build)
# -*- coding: utf-8 -*-
import sys,os
from cx_Freeze import setup, Executable
PythonPath = os.path.split(sys.executable)[0] #get python path
includes = []
excludes = []
packages = ["win32print"]
includefiles = ["OptiWeb.ico"]
options = {"includes": includes,
"excludes": excludes,
"packages": packages,
"include_files": includefiles,
"optimize":2
}
base=None
if sys.platform == 'win32':
base = "Win32GUI"
options["include_msvcr"] = True
executables = [Executable(script="OptiPrint.py",base=base,icon="Optiweb.ico")]
setup(name = "OptiPrint",options = {"build_exe": options},version = "1.0",author = "ND",description = "print test",executables = executables)
And now my code for printing:
# coding: utf8
import win32print
class ZPLLabel(object):
def __init__(self, printerName):
self.printerName = printerName
self.printerDevice = win32print.OpenPrinter(self.printerName)
self.job = win32print.StartDocPrinter(self.printerDevice, 1, ("Etiquette", None, "RAW"))
self.eraseAll()
self.defineFormat()
def eraseAll(self):
win32print.StartPagePrinter(self.printerDevice)
str2print="~JA"
win32print.WritePrinter(self.printerDevice, str2print.encode("utf8")) #écrit le format d'étiquette
win32print.EndPagePrinter(self.printerDevice) # indique la fin de ce qu'il y a à imprimer
self.printerDevice.close() # ferme le canal d'impression et déclenche l'impression de ce qui précède
#del self.job
self.printerDevice=win32print.OpenPrinter(self.printerName)
self.job = win32print.StartDocPrinter(self.printerDevice, 1, ("Etiquette", None, "RAW"))
def defineFormat(self):
margeLeft = 150
margeTop = 20
interLine = 39
shiftLeft = 20
vDec = 25
#win32print.StartPagePrinter(p)
str2print="^XA\n" #debut de format
str2print+="^CI28"
#FO origine du champ, 100 pos x du champ en dots, 50 pos y du champ en dots
# l'imprimantes est 200 dpi (dotsper inch = 7.874 dots par mm, ici 12.7mm, 6.35mm)
#ADN : A ==> font, D==> font D, N ==> Orientation Normale, 36 hauteur caractère en dots, 20 Largeur caractère en dots
#FD données à imprimer pour le champ
#FS fin du champ
str2print+="^DFFORMAT"
str2print+="^LH"+str(margeLeft)+","+str(margeTop)
#un cadre arrondi
str2print+="^FO0,0^GB500,330,3,B,2^FS"
#str2print+="^FO"+str(shiftLeft)+","+str(interLine)+"^ADN,24,12^FDEtiquette de débit Sangle^FS\n" #format de l'étiquette
str2print+="^FO"+str(shiftLeft)+","+str(1*interLine-vDec) +"^ADN,32,14^FDOF N° : ^FS^FO"+str(shiftLeft+160)+","+str(1*interLine-vDec) +"^ADN,32,14^FN1^FS"
str2print+="^FO"+str(shiftLeft)+","+str(2*interLine-vDec) +"^ADN,32,14^FDPRODUIT : ^FS^FO"+str(shiftLeft+215)+","+str(2*interLine-vDec) +"^ADN,32,14^FN2^FS"
str2print+="^FO"+str(shiftLeft)+","+str(3*interLine-vDec) +"^ADN,24,12^FN3^FS"
str2print+="^FO"+str(shiftLeft)+","+str(4*interLine-vDec) +"^ADN,32,14^FDSANGLE : ^FS^FO"+str(shiftLeft+200)+","+str(4*interLine-vDec) +"^ADN,32,14^FN4^FS"
str2print+="^FO"+str(shiftLeft)+","+str(5*interLine-vDec) +"^ADN,24,12^FN5^FS"
str2print+="^FO"+str(shiftLeft)+","+str(6*interLine-vDec) +"^ADN,28,13^FDNombre de coupe : ^FS^FO"+str(shiftLeft+250)+","+str(6*interLine-vDec) +"^ADN,28,13^FN6^FS"
str2print+="^FO"+str(shiftLeft)+","+str(7*interLine-vDec) +"^ADN,28,13^FDLongueur coupée : ^FS^FO"+str(shiftLeft+250)+","+str(7*interLine-vDec) +"^ADN,28,13^FN7^FS"
str2print+="^FO"+str(shiftLeft)+","+str(8*interLine-vDec) +"^ADN,24,12^FDEmplacement : ^FS^FO"+str(shiftLeft+160)+","+str(8*interLine-vDec) +"^ADN,24,12^FN8^FS"
str2print+="^XZ" # fin du format d'étiquette
win32print.WritePrinter(self.printerDevice, str2print.encode("utf8")) #écrit le format d'étiquette
def printLabel(self, orderNum, productSku, productName, webSku, webName, partNum, partLength, emplacement):
str2print="^XA\n" #debut étiquette
str2print+="^XFFORMAT" #rappel du format enregistré
str2print+="^FN1^FD"+orderNum+"^FS"
str2print+="^FN2^FD"+productSku+"^FS"
str2print+="^FN3^FD"+productName+"^FS"
str2print+="^FN4^FD"+webSku+"^FS"
str2print+="^FN5^FD"+webName+"^FS"
str2print+="^FN6^FD"+str(partNum)+"^FS"
str2print+="^FN7^FD"+partLength+"^FS"
str2print+="^FN8^FD"+emplacement+"^FS"
str2print+="^XZ" # fin du format d'étiquette
win32print.WritePrinter(self.printerDevice, str2print.encode("utf8")) #écrit l'étiquette
def endLabel(self):
self.printerDevice.close() # ferme le canal d'impression et déclenche l'impression de ce qui précède
del self.job
def newPrintLabel():
zpl = ZPLLabel('Zebra ZP 450 CTP')
zpl.printLabel("20009999", "1035691", "Harnais Energy TWIN ss porte outil L/XL",
"90008318", "SA/SANGLE NOIRE 20 MM", 35, "0.38m", "Bavaroise réglable")
zpl.endLabel()
if __name__ == '__main__':
app = newPrintLabel()
I suppose, some package or dll is missing to make it run when frozen.
I tried to add win32api, win32com but it doesn't change the result.
Thanks for your help which is for sure welcome.
Try to use win32ui and win32con as done in the answers of python win32print not printing.
In this case you should also keep base defined as in your original question (regarding my comment to your question).
For those who experiment a such issue.
My code was not properly written:
To each StartDocPrinter instruction must correspond a EndDocPrinter instruction, apparently this not cause trouble with script but has impact on frozen version.
So the correct thread of instructions must be something like:
self.printerName = printerName
self.printerDevice = win32print.OpenPrinter(self.printerName)
self.job = win32print.StartDocPrinter(self.printerDevice, 1, ("Etiquette", None, "RAW"))
win32print.StartPagePrinter(self.printerDevice)
str2print="..." # define what you want to print
win32print.WritePrinter(self.printerDevice, str2print.encode("utf8")) #write
win32print.EndPagePrinter(self.printerDevice) # end the page
win32print.EndDocPrinter(self.printerDevice) # end the doc
self.printerDevice.close() # close the printer thread

correct way to implement thread python

I am implement a simple simulator of soccer with python using threads and lock, the app works fine but I have doubts in the way that implement the thread it seems to me that the first team has an advantage because is executing first.
def jugar(Equipo1, Equipo2):
# Busco las probabilidades de encajar por cada equipo
prob_encajar_eq1 = Equipo1.probabilidad_encajar()
prob_encajar_eq2 = Equipo2.probabilidad_encajar()
def jugar_equipo1(defensa_rival):
semaforo.acquire()
if Equipo1.hacer_pases():
Equipo1.shoot(defensa_rival)
semaforo.release()
def jugar_equipo2(defensa_rival):
semaforo.acquire()
if Equipo2.hacer_pases():
Equipo2.shoot(defensa_rival)
semaforo.release()
hilo_equipo1 = threading.Thread(name = 'hilo_eq1', target = jugar_equipo1, args = (prob_encajar_eq2,))
hilo_equipo2 = threading.Thread(name = 'hilo_eq2', target = jugar_equipo2, args = (prob_encajar_eq1,))
hilo_equipo1.start()
hilo_equipo2.start()
hilo_equipo1.join()
hilo_equipo2.join()
to make several attempts both teams, I do a cicle for a few seconds and inside the function jugar() which is the one that does the work with threads but here is were I have the doubts, because every time that jugar is executing the threads are declared again.
if __name__ == '__main__':
cargar_informacion()
eqA = Equipo(equipoA, ranking_eqA)
eqB = Equipo(equipoB, ranking_eqB)
probabilidades = porcenajes_ranking(ranking_eqA)
eqA.cargar_probabilidades(probabilidades)
probabilidades = porcenajes_ranking(ranking_eqB)
eqB.cargar_probabilidades(probabilidades)
starttime=time.time()
tiempo = 0
# creo la barra de progreso
bar = progressbar.ProgressBar(widgets=[
progressbar.Percentage(),
progressbar.Bar(),
], max_value=100).start()
# hacemos que el juego tarde aproximadamente 10seg en simularse.
while tiempo < 10:
time.sleep(0.3 - ((time.time() - starttime) % 0.3))
jugar(eqA,eqB)
tiempo = time.time() - starttime
bar += 2.8
bar.finish() # Para que finalice la barra de progreso
resultados_finales(eqA, eqB) # Mostramos el resultado final del partido.

UPDATE mysql error with Python

Here's my situation:
I got a table on a database, as following:
nome_imagem estado type
57260-tracker-_tracker_face awake 0
57261-tracker-_tracker_face drowsiness 1
57268-tracker-_tracker_face noface 2
57289-tracker-_tracker_face distracted 3
57290-tracker-_tracker_face awake 1
57291-tracker-_tracker_face drowsiness 2
57293-tracker-_tracker_face noface 3
And I want to update de type column according to serveral if conditions, but I'm getting a error on line 29:
mysql.connector.errors.InternalError: Unread result found
I'm pretty sure its the way im making the query, and I already searched another questions about this before opening this one, but I couldnt solve it anyway.
EDIT 1: Changed the query and applied the solution gave by gzc to get rid of the error, but now it updates all the type column instead of just the cases where the if is true
import mysql.connector
from mysql.connector import errorcode
import os
cnx = mysql.connector.connect(user='root', database='empresa')
cursor = cnx.cursor()
fileDir = os.path.dirname(os.path.realpath(__file__))
textDir = os.path.join(fileDir, "test_img")
query = ("SELECT nome_imagem, estado, type FROM alertas ")
cursor.execute(query)
results = list(cursor)
for (nome_imagem, estado, type) in results:
print nome_imagem, estado
my_file_name = nome_imagem+'.txt'
my_file = open("test_img/"+my_file_name, 'r')
content = my_file.readline()
status = content.strip().split()[-1].split("=")[1]
face = content.strip().split()[0].split("=")[1]
print status, face #1 tem face, 0 nao tem
if (face == '1' and estado == status): #se tem cara e o estado que tem na bd for igual ao estado que o programa classificou = correto
print "correto"
cursor.execute("UPDATE alertas SET type='1' WHERE nome_imagem=nome_imagem")
if (face == '1' and estado == 'drowsiness' and status == 'awake') or (face == 1 and estado == 'awake' and status == 'drowsiness'): #verificar isto
print "trocado"
if (estado != '' and face == '0'): # se tiver estado mas nao tiver cara classifico logo como errado 3
print "errado"
if (estado == 'distracted' and face == '1'): # se tem cara mas for distracted deixo normal pois nao consigo classificar
print "normal"
cursor.close()
cnx.close()
What am I doing wrong?
Thanks
EDIT 2: gzc solver it again :)
You must read all results before doing another operation on the same cursor.
...
query = ("SELECT nome_imagem, estado, type FROM alertas ")
cursor.execute(query)
results = list(cursor)
for (nome_imagem, estado, type) in results:
...

Python multiple processes do not loop on for

I'm working on the implementation of several algorithms to compute shortest paths on graphs.
I have managed to implement Dijkstra's algorithm sequentially and I'm now trying to optimize my algorithm through the multiprocessing module of Python.
As a whole the code works. What I am trying to do here is :
First to check how many cpus I can work on with nb_cpu = mp.cpu_count()
Then dividing all the nodes I have in my graph accordingly
Finally calling the method subprocess_dijkstra that should compute the dijkstra algorithm for each of the nodes it is given as an argument (the idea being that each process only has to compute the algorithm for a smaller part of the graph).
When I run my script (called from a main.py file where I just format the data to suit my needs), I have 4 processes launched as I should.
However, they do not seem to execute the for node in nodes loop defined in subprocess_dijkstra.
Each process only computes the code once and then they go on hold indefinitely...
It is my first attempt at multiprocessing under Python so I may have missed a detail. Does anybody have an idea ?
When I interrupt the script, python tells me that the interruption takes place on the p.join() line.
Thanks to anyone helping me :)
Here is my code :
import multiprocessing as mp
def subprocess_dijkstra(do_print, nodes, tab_contenu, tab_distances):
tab_dist_initial = dict(tab_distances)
tab_dist = dict()
for node in nodes:
visited_nodes = list()
tab_dist = dict(tab_dist_initial)
dmin = -1
resultat = ""
filename = "dijkstra"+str(node)+".txt"
if do_print:
dt = open(filename, 'w')
tab_dist[node] = 0
"""Ligne de résultat initiale"""
for valeur in tab_dist.values():
resultat += str(valeur)
resultat += " "
resultat += "\n"
dt.write(resultat)
while len(visited_nodes) != len(tab_contenu):
""" On se place sur le noeud non visité qui a la distance minimale de notre départ """
for cle, valeur in tab_dist.items():
if cle not in visited_nodes:
if dmin ==-1 or valeur<dmin:
dmin = valeur
node = cle
""" On vérifie que le noeud n'a pas déjà été visité """
if (node not in visited_nodes):
""" On regarde les fils de ce noeud et la longueur des arcs"""
for cle,valeur in tab_contenu[node].items():
tab_dist[cle] = min(tab_dist[cle], tab_dist[node]+valeur)
visited_nodes.append(node)
if do_print:
resultat = ""
""" Ligne de résultat """
for valeur in tab_dist.values():
resultat += str(valeur)
resultat += " "
resultat += "\n"
dt.write(resultat)
if do_print:
dt.close()
def main(do_print,donnees):
tab_contenu = donnees[1]
nb_nodes = int(donnees[0])
tab_distances = {x: float('inf') for x in range(nb_nodes)}
args=[(do_print, x, tab_contenu, tab_distances) for x in range(nb_nodes)]
nb_cpu = mp.cpu_count()
pool = mp.Pool(processes = nb_cpu)
pool.starmap(subprocess_dijkstra, args)
pool.close()
pool.join()
I have found the source of my problems.
The tab_dist[node] = 0 was misplaced and should have been put before the if do_print: statement.
All is now working.

Categories