I am trying to make a simple simulation of communication between two devices via serial ports(on linux to be clear). I have came up with idea to put reading from serial port into diffrent thread, but the problem is that this thread throw me an error like this:
Is open? True
Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib/python3.7/threading.py", line 926, in _bootstrap_inner
self.run()
File "/usr/lib/python3.7/threading.py", line 870, in run
self._target(*self._args, **self._kwargs)
File "client.py", line 18, in func
if len(ser.readline()) > 0:
File "/home/bartosz/PycharmProjects/socket-serial-comm/venv/lib/python3.7/site-packages/serial/serialposix.py", line 478, in read
raise portNotOpenError
serial.serialutil.SerialException: Attempting to use a port that is not open
So it seems that port I am trying to use is not open, but when I am printing from this thread print("Is open? ", ser.is_open)
it gives me True, and I can't open the port in thread because of that.
Here's my code:
import serial
import threading
import time
ser = serial.Serial('/dev/pts/0', timeout=1)
def func():
print("Is open? ", ser.is_open)
while True:
if len(ser.readline()) > 0:
print(ser.readline())
x = threading.Thread(target=func, args=ser)
x.start()
time.sleep(1)
ser.write(b'some text\n')
time.sleep(1)
ser.close()
Any thoughts why this behave like that?
This is working exactly as you coded it.
The process that is reading the serial port is running forever in an infinite loop with While True:, but the port itself is ser.close() about 2 seconds after the processing thread is started.
Since ser.readline() is executed even after ser.close(), the question error occurs.
Before calling ser.close(), you need to install a mechanism to terminate def func(): thread processing.
By the way, the process of judging with len(ser.readline()) in if statement and then print(ser.readline()), there is data requires input of two lines, but the first line is not displayed, it would be weird to just print the next line.
You should review the process.
Related
Okay i want to program a server with python.
Therefore i opened a socket and wait for the input.
When i get an input i get an further socket and and address.
Because I want to implement multiple connections at the same time I looked into multi-threading in python.
I create a thread the following way:
t = Thread(target=input, args=(conn, address, ))
t.start()
My input method looks the following:
def input(conn, address): [...]
Now if in this way I get the following stacktrace:
Exception in thread Thread-1:
Traceback (most recent call last): File "/usr/lib/python3.8/threading.py", line 932, in _bootstrap_inner
self.run()
File "/usr/lib/python3.8/threading.py", line 870, in run
self._target(*self._args, **self._kwargs)
TypeError: input expected at most 1 argument, got 2
If i remove the address (and just give the conn) it prints the following:
<socket.socket fd=4, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('10.0.0.9', 3306), raddr=('10.0.0.9', 32908)>
How should I understand that?
Solution to the problem:
I need to call the method via self.input not input.
input is a build-in python function which gets one argument so when you are trying to use input inside threading python supposed you want to use the built-in input function. change the function name will fix the issue:
def _input(conn, address): [...]
t = Thread(target=_input, args=(conn, address, ))
t.start()
PS: this way is not a good way to handle multithread networking
I'm making a python server to keep connected 3 clients. I have finished all and now, when I'm doing the stdin commands for the server (like quit, see (client), etc) I realised I have an apparently big problem for me:
This is the structure:
import sys, os, traceback, optparse
import time, datetime
import random
import socket
import thread
import select
while True:
data,addr = dad_sock.recvfrom(UDP)
if(data != ""):
print "First_Data:",sys.stdin.readline()
thread.start_new_thread(MAIN_son,(UDP,data,addr,number_sons))
number_threads += 1
print "Second_Data:",sys.stdin.readline()
What MAIN_son does is to create a new thread wich look for pkg recived and keep the clients connected to the server.
And here is my problem:
Data: ERROR, UNEXPECTED EXCEPTION
I/O operation on closed file
Traceback (most recent call last):
File "srv.py", line 588, in
start()
File "srv.py", line 136, in start
main()
File "srv.py", line 481, in main
setup()
File "srv.py", line 164, in setup
dad_wait(srv.UDP,number_sons)
File "srv.py", line 172, in dad_wait
print "Data:",sys.stdin.readline()
ValueError: I/O operation on closed file
Line 172 is my first read from stdin() but the program lets me to do it so I think its at the second round of the while when it fails
I need to say that when MAIN_son thread is called starts to print all the pkg info from the client pakages. I don't know if this prints can be the cause.
If someone needs more information about the code I'll refresh the question, Thanks
I'm trying to connect to host by different threads in python but getting error sometimes(1 times in 25 times execution)
I have seen similar threads and hoped to update pip to 8.1.1 will solve this but did not solve though.
code snippet:
def getkpis(self,cmd,host):
ssh=paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
ssh.connect(host,username='root',look_for_keys=True)
stdin, stdout, stderr = ssh.exec_command(cmd)
paramiko.util.log_to_file("kpiparamiko.log")
output=stdout.read()
appendarray=output.split('\n')
sys.stdin.flush()
ssh.close()
except paramiko.SSHException, e:
print str(e)
Error seen:
Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib64/python2.7/threading.py", line 811, in __bootstrap_inner
self.run()
File "/usr/lib64/python2.7/threading.py", line 764, in run
self.__target(*self.__args, **self.__kwargs)
File "/conf/home/smodugu/kpiparse.py", line 56, in getkpis
ssh.connect(host,username='root',look_for_keys=True)
File "/usr/lib/python2.7/site-packages/paramiko/client.py", line 338, in connect
t.start_client()
File "/usr/lib/python2.7/site-packages/paramiko/transport.py", line 493, in start_client
raise e
RequirementParseError: Invalid requirement, parse error at "''"
Yesterday, I was able to get around this by using an older version of setuptools, pip install "setuptools<34" but then today the problem came back. I was able to get around it by adding a 0.1 second sleep in the loop that was queuing the threads. Why multiple threaded calls to paramiko's SSHClient cause this error with pip/setuptools, I have no idea.
It looks like the connect function is not thread safe in the version of paramiko for python2.7
The solution is to use the Lock object from the threading module,
from threading import Lock.
Then wrap the call to the connect function of the paramiko client with the lock object.
For example:
from threading import Lock
lock = Lock()
...
lock.acquire()
client.connect(...)
lock.release()
The code above makes so that only one thread will use the connect at a time, which solves the problem that the function is not thread safe.
*** I am not sure if the problem exists in newer versions of paramiko, worth a look.
Im trying to control arduino using Python. So, i wonder how can I create a python program that takes a string variable(a word that I will type in python serial) and send it to arduino serial port.
im getting this error
Enter Message:Exception in thread Thread-1:
Traceback (most recent call last):
File "C:\Python27\lib\threading.py", line 810, in __bootstrap_inner
self.run()
File "C:\Python27\lib\threading.py", line 763, in run
self.__target(*self.__args, **self.__kwargs)
File "C:\Users\JohnC\Desktop\trial.py", line 69, in serialThread
s.close()
UnboundLocalError: local variable 's' referenced before assignment
import serial
ser = serial.Serial("ArduinoComPortNumber",9600,timeout=1)
for message in iter(lambda:raw_input("Enter Message:"),""):
msg_with_newline = message+"\n"
print "You Say:",repr(msg_with_newline)
ser.write(msg_with_newline)
print "Arduino Says:",repr(ser.read(10000))
I made it more readable :P
you could do the actual serial comm in the thread this would allow you to see output while you were getting ready to type...
pending_send_messages = []
def serialThread(comPort):
try:
s = serial.Serial(comPort,9600,timeout=0.5)
while True:
print "Arduino Says:",repr(s.read(1000))
if pending_send_messages:
print "You Say:",pending_send_messages[0]
if not pending_send_messages[0]:break;
s.write(pending_send_messages.pop(0)+"\n")
finally:
s.close()
import threading
t = threading.Thread(target=serialThread,args=("COM11",)) #make sure to use appropriate com port
t.start()
for message in iter(lambda:raw_input("Enter Message:"),""):
pending_send_messages.append(message)
pending_send_messages.append(0)
I am trying a write a python code having multiple processes whose structure and flow is something like this:
import multiprocessing
import ctypes
import time
import errno
m=multiprocessing.Manager()
mylist=m.list()
var1=m.Value('i',0)
var2=m.Value('i',1)
var3=m.Value('i',2)
var4=m.Value(ctypes.c_char_p,"a")
var5=m.Value(ctypes.c_char_p,"b")
var6=3
var7=4
var8=5
var9=6
var10=7
def func(var1,var2,var4,var5,mylist):
i=0
try:
if var1.value==0:
print var2.value,var4.value,var5.value
mylist.append(time.time())
elif var1.value==1:
i=i+2
print var2.value+2,var4.value,var5.value
mylist.append(time.time())
except IOError as e:
if e.errno==errno.EPIPE:
var3.value=var3.value+1
print "Error"
def work():
for i in range(var3.value):
print i,var6,var7,va8,var9,var10
p=multiprocessing.Process(target=func,args=(var1,var2,var4,var5,mylist))
p.start()
work()
When I run this code, sometimes it works perfectly, sometimes it does not run for exact amount of loop counts and sometimes I get following error:
0
1
Process Process-2:
Traceback (most recent call last):
File "/usr/lib64/python2.6/multiprocessing/process.py", line 232, in _bootstrap
self.run()
File "/usr/lib64/python2.6/multiprocessing/process.py", line 88, in run
self._target(*self._args, **self._kwargs)
File "dummy.py", line 19, in func
if var1.value==0:
File "/usr/lib64/python2.6/multiprocessing/managers.py", line 1005, in get
return self._callmethod('get')
File "/usr/lib64/python2.6/multiprocessing/managers.py", line 722, in _callmethod
self._connect()
File "/usr/lib64/python2.6/multiprocessing/managers.py", line 709, in _connect
conn = self._Client(self._token.address, authkey=self._authkey)
File "/usr/lib64/python2.6/multiprocessing/connection.py", line 149, in Client
answer_challenge(c, authkey)
File "/usr/lib64/python2.6/multiprocessing/connection.py", line 383, in answer_challenge
message = connection.recv_bytes(256) # reject large message
EOFError
What does this error mean? What wrong am I doing here? What this error indicates? Kindly guide me to the correct path. I am using CentOS 6.5
Working with shared variables in multiprocessing is tricky. Because of the python Global Interpreter Lock (GIL), multiprocessing is not directly possible in Python. When you use the multiprocessing module, you can launch several task on different process, BUT you can't share the memory.
In you case, you need this so you try to use shared memory. But what happens here is that you have several processes trying to read the same memory at the same time. To avoid memory corruption, a process lock the memory address it is currently reading, forbidding other processes to access it until it finishes reading.
Here you have 3 processes trying to evaluate var1.value in the first if loop of your func : the first process read the value, and the other are blocked, raising an error.
To avoid this mechanism, you should always manage the Lock of your shared variables yourself.
You can try with syntax:
var1=multiprocessing.Value('i',0) # create shared variable
var1.acquire() # get the lock : it will wait until lock is available
var1.value # read the value
var1.release() # release the lock
External documentation :
Locks : https://docs.python.org/2/librar/multiprocessing.html#synchronization-between-processes
GIL : https://docs.python.org/2/glossary.html#term-global-interpreter-lock