Python Threading not processed parallel - python

I'm intermidiate bee for python and would like to run the same class instances of few in parallel mode for fetching data and decision making for financial market. To proceed my idea, I run the following code to see how python works, it seems it works one complete run of first class instance and after second class instances, I would like to run this parallely, how can I...?
Below is the some sample code for testing..
import threading
import time
class thr(object):
def __init__(self, name):
self.name = name
self.x = 0
def run(self):
for i in list(range(10)):
self.x +=1
print("something {0} {1}".format(self.name, self.x))
time.sleep(1)
F = thr("First")
S = thr("Second")
threading.Thread(target=F.run())
threading.Thread(target=S.run())
and the results as below....
something First 1
something First 2
something First 3
something First 4
something First 5
something First 6
something First 7
something First 8
something First 9
something First 10
something Second 1
something Second 2
something Second 3
something Second 4
something Second 5
something Second 6
something Second 7
something Second 8
something Second 9
something Second 10
Out[27]: <Thread(Thread-25, initial)>

The problem is here:
threading.Thread(target=F.run())
threading.Thread(target=S.run())
target= takes a callable object or None. F.run() executes F.run immediately, waits for it finish, and then passes the return value (which is None in your run() method) as the target.
You want something like this instead:
t1 = threading.Thread(target=F.run)
t2 = threading.Thread(target=S.run)
t1.start()
t2.start()
Note that there's no parentheses after run
Here's the complete program with the suggested change:
import threading
import time
class thr(object):
def __init__(self, name):
self.name = name
self.x = 0
def run(self):
for i in list(range(10)):
self.x +=1
print("something {0} {1}".format(self.name, self.x))
time.sleep(1)
F = thr("First")
S = thr("Second")
t1 = threading.Thread(target=F.run)
t2 = threading.Thread(target=S.run)
t1.start()
t2.start()
And output (Python 3.6.1):
$ python sf.py
something First 1
something Second 1
something Second 2
something First 2
something Second 3
something First 3
something Second 4
something First 4
something Second 5
something First 5
something Second 6
something First 6
something Second 7
something First 7
something First 8
something Second 8
something First 9
something Second 9
something First 10
something Second 10

Related

Can I continue an input after a new line is created

I want to make my input continue after a new line is created in the terminal.
Here's the quick script I wrote:
import threading, time
def inn():
while True:
input()
def count():
a=0
while True:
a+=1
print(a)
time.sleep(1)
t1 = threading.Thread(target=inn)
t2 = threading.Thread(target=count)
t1.start()
t2.start()
Is there any way I could accomplish this, preferably with in-built functions.
if you change your code to:
.
def inn(): # in is restricted name in python
while True:
print(input())
.
.
.
you will notice that your code already does what you want! Even though it doesn't look like so, the input is not interrupted, take a look at the program:
1
2
t3
his 4
iss 5
my 6
strin7
g 8
this iss my string
9
The only change your code needs is to change restricted name in.

How do I loop my python code a specific number of times?

I've been struggling to loop my code a specific number of times. I've YouTubed mulitple videos on while statements for looping but it never works. I have gotten to a point where I managed to run the code but then once it ran once it started looping and listing number 1 - 10. I'm assuming this is because I specified <10 to loop. I don't think I'm understanding but I am a visual learner and the text examples aren't helping. Here's the code I would like to loop.
import urllib.request
import os
urllib.request.urlretrieve("https://websitewithimageonit.com/", "")
i = 0
while os.path.exists("image%s.jpg" % i):
i += 1
fh = open("image%s.jpg" % i, "w")
I tried to do it myself and used a while loop like this below. The code ran, saved 1 image but then just listed 1 - 10 in the PyCharm console.
import urllib.request
import os
import time
urllib.request.urlretrieve("https://websitewithimageonit.com/", "")
i = 0
while os.path.exists("image%s.jpg" % i):
i += 1
fh = open("image%s.jpg" % i, "w")
condition = 1
while condition < 10:
print(condition)
condition += 1
After it runs the code it prints this in the console
1
2
3
4
5
6
7
8
9
Process finished with exit code 0
Which I'm assuming is me messing up the while loop. Where am I going wrong? Thanks
I think you wanted to do something like:
i = 0
while os.path.exists(f"image{i}.jpg"):
with open(f"image{i}.jpg", "w") as fh:
#do stuff with the file here
#do other stuff here
#at the end of the loop, increment i
i += 1
Read the following for more info
https://www.geeksforgeeks.org/with-statement-in-python/
https://www.geeksforgeeks.org/formatted-string-literals-f-strings-python/
You can combine for loop with range function
so if you want to do 50 times something here is the loop
for times in range(50):
print("x")

Python SimPy: yield env.timeout not working

I'm just getting started with SimPy so maybe I'm missing something major here. I have a very simple Process which I want to just increment a number once per second.
class Simulation:
def __init__(self):
self.env = simpy.Environment()
thing = Thing()
p = self.env.process(thing.go(self.env))
self.env.run()
simulation = Simulation()
class Thing():
def __init__(self):
self.x = 1
def go(self,env):
while True:
self.x = self.x + 1
print("Current value: {}".format(self.x))
yield env.timeout(1)
The timeout seems to be getting ignored here. It doesn't matter what value I pass as the delay, or whether I include the line at all, x increases at the same rate(over 1 million within seconds)
You seem to be confusing real-time with sim-time. Have your print statement include the current time (env.now). You should get something like this:
Current value: 2 , time now: 0
Current value: 3 , time now: 1
Current value: 4 , time now: 2
Current value: 5 , time now: 3
:
So, you can see the simulation clock is incrementing as is should; the simulation is just really fast. If you want to run in real time, don't use simpy.environment(). Instead, use simpy.rt.RealTimeEnvironment().
See here for more details:
https://simpy.readthedocs.io/en/latest/topical_guides/real-time-simulations.html

Delay function result while still being able to call the function and make result available

I want my function delayed_sum(value, delay) to add the value to a global variable result with a certain delay in Python 3.x.
The idea is to connect my Python code with Electron to have a user interface. The user interface lets you view this global variable called result and let's you add some value to result with a certain delay expressed in seconds.
I would like the variable result to be updated as soon as the delay has elapsed and while the function is running in the background, still be able to call the function.
If we have the time in seconds as follow:
Initialisation of result to 0 and display of 0 on the UI
delayed_sum(5, 10) called. In 10 seconds, add 5 to result
Add 5 in 9 seconds
Add 5 in 8 seconds
Add 5 in 7 seconds
Add 5 in 6 seconds
Add 5 in 5 seconds
Add 5 in 4 seconds
Add 5 in 3 seconds and delayed_sum(3, 5) called. In 5 seconds, add 3 to result
Add 5 in 2 seconds and in 4 seconds add 3
Add 5 in 1 second and in 3 seconds add 3
result += 5 and the UI displays 5 and in 2 seconds add 3
In 1 second add 3
result += 5 and the UI displays 8
I tried using time.sleep() but it freezes the control panel and I'm not able to call delayed_sum() while a first delayed_sum is being executed.
import time
import threading
result = 0
def delayed_sum(value, delay):
t = threading.Thread(target=perform_sum, args=(value,delay,))
t.start()
def perform_sum(value, delay):
global result
time.sleep(delay)
result += value
When I use the code above, the action is indeed performed, but the result value isn't updated in the variable explorer before an other command line is executed.
I still haven't used Electron, but I'm afraid that if I ask my UI to read the value of result, what will be displayed won't be in real time. Could you guide me in making sure the UI will indeed read the correct value of result?
Many thanks!

python class variable won't updated in multiprocessing

I am using multiprocessing to faster a long process in python and I want to save my data in a separate class in order to make code a little cleaner but it seems that whether I change class var in the process it will roll back to the last state before the process, while in proceed it show that variable is updated.
here is simplified example
class state_mangment():
def __init__(self):
print('__init__')
self.last_save = -1
def update_state(self):
self.last_save =self.last_save + 1
return self.last_save
from multiprocessing import Process, Lock
def f(l, i,persist_state ):
l.acquire()
try:
print('last save is ',persist_state.update_state(),' should be ',i)
finally:
l.release()
if __name__ == '__main__':
lock = Lock()
persist_state = state_mangment()
processes = []
for num in range(10):
p = Process(target=f, args=(lock, num,persist_state ))
processes.append(p)
p.start()
for p in processes:
p.join()
print(persist_state.last_save)
here is the output, as you can see increase variable from -1 to 0 as we can see in return value but it won't start from 0 in next iteration
__init__
last save is 0 should be 0
last save is 0 should be 1
last save is 0 should be 2
last save is 0 should be 3
last save is 0 should be 4
last save is 0 should be 5
last save is 0 should be 6
last save is 0 should be 7
last save is 0 should be 8
last save is 0 should be 9
-1
There are several things wrong with your code. A function run by multiprocessing.Process() does not share the address space of the parent process. Which is why the manipulation of the persist_state object is not reflected in the parent process. That you can use a multiprocessing.Lock() object in this fashion is because that class was designed to work in that fashion when used in a multiprocessing.Process() context. That does not mean you can manipulate the state of arbitrary objects and have those manipulations reflected in the parent process.
See this description of the Manager() class for one way to solve this problem.

Categories