-1

I'm trying to share the class instance/object variables with other processes that I start within it, since I need to run multiple function at the same time, to record macros from the keyboard & mouse and re-play them latter at the same timing.

I see that it's possible to use multiprocessing.Manager, but i'm using concurrent.futures.ThreadPoolExecutor. is there a similar function there?

I wrote the code below now to clarify. The actual code has a setState function for settings the recording state and such, and the key that's pressed doesn't get passed. Also, the actual code obviously has a listener for the key presses and mouse moves, the getKey and getMove functions should be the ones appending to the list. The problem in this case is that the recording variable can't be accessed from the second process that should start recording moves once the "Insert" key is pressed. A function in concurrent that's similar to Manager in multiprocessing would solve it, but i'm not sure what it's called or to use it.

from concurrent.futures import ThreadPoolExecutor as Executor
import time

class recMacros(object):
    def __init__(self):
        self.recording = False

        self.lastKey = None
        self.lastMove = None

        self.mouseMoves = []
        self.keyPresses = []

        self.runMacros()


    def getTime(self):
        return time.time()

    def getKey(self):
        #return keyboard listener last key pressed
        return "W"

    def getMove(self):
        #return keyboard listener last key pressed
        return "W"

    def recMoves(self): 
        while True:
            while self.recording:
                mouseMove = self.getMove()
                if mouseMove != self.lastMove:
                    self.mouseMoves.append((mouseMove, self.getTime()))
                    self.lastMove = mouseMove

    def recPresses(self):
         while True:
             keyPress = self.getKey()
             if keyPress == "Insert":
                self.recording = True
             elif keyPress == "End":
                self.recording = False
             elif self.recording and keyPress != self.lastKey:
                self.keyPresses.append((keyPress, self.getTime()))
                self.lastKey = keyPress
             else:
                 print("Error")

    def recMacros(self):
        with Executor(max_workers=2) as e:
            e.submit(recPresses)
            e.submit(recMoves)

if __name__ == "__main__":
     recMacros()

I'd appreciate some quick direction since i'm in a rush. Thanks in advance

@user2357112 supports Monica Here's the code I used to test the timing, to verify that ThreadPoolExecutor is like a process to comes to running the functions in parallel:

from concurrent.futures import ThreadPoolExecutor
import time

def printTime():
    print(f"Time: {time.time()}\n")


def runPro():
    with ThreadPoolExecutor(max_workers=3) as e:
        for i in range(3):
            e.submit(printTime)


runPro()
Waleed Qutob
  • 57
  • 1
  • 3
  • 7
  • `concurrent.futures.ThreadPoolExecutor` isn't multiprocessing. The distinction is *really important* - using separate processes behaves very differently from using threads, despite `multiprocessing`'s attempt to make its interface look like `threading`. – user2357112 Feb 28 '20 at 03:09
  • Thanks. I did suspect that it's a multithreading library and not a multiprocessing one, but when I tested it multiple functions ran at the same exact time, which is what I need. Regardless, the variables didn't get shared when I tested it, which means that the address space is different, like it's a process. A solution like Manage would be appreciated, i'm on a tight schedule. I'll add the code I used to test the timing to the thread, as it makes the comment exceed the limit and can't be added here. – Waleed Qutob Feb 28 '20 at 03:20
  • No, `ThreadPoolExecutor` doesn't do anything to the address space. If it looked like you had a separate address space, what you really had was a bug. – user2357112 Feb 28 '20 at 03:21
  • Makes sense, it's called "ThreadPoolExecutor" for a reason. Just to be clear, the variable value doesn't get updated in the other threads, what kind of bug could it be? I update the equivalent of self.recording value to False and it doesn't change. – Waleed Qutob Feb 28 '20 at 03:26
  • 1
    We can't really tell, since the code you posted doesn't reproduce the problem. (The code you posted fails for entirely different reasons.) If we had a [mcve], we might be able to identify the bug. – user2357112 Feb 28 '20 at 03:32
  • You're right, it's a bug. Sometimes the value gets updated and other times it doesn't. it seems to be that's it's the amount of threads that's causing the issue, it's best to use multiprocessing. is there a way to contact you directly? i'm not sure if it's allowed on here, but i'm willing to pay you to help me on Teamviewer. – Waleed Qutob Feb 28 '20 at 04:04
  • As I said, i'm on a tight schedule and it's best if I can get it done in a couple hours. I just need to replace ThreadPoolExecutor with multiprocessing and fix a couple other things. i'd appreciate it if you can help with a bit more, I want to replace the clicks listener with one that listens directly to the Windows API through the ctypes library, the code for moves is already written, but not the click, the one for pressing & releasing keys is done as well, but I can't figure out how to read the keys for one for capturing. Let me know if interested, it shouldn't take more than an hour or two. – Waleed Qutob Feb 28 '20 at 04:04

1 Answers1

-1

If you want to save something in a variable that every process can use, you can use queue.

  1. Import queue
import queue
  1. Create a shared variable
shared_var = queue.Queue(maxsize=0)

where maxsize is the maximum that can be saved in this queue

  1. Edit shared variable in any process
shared_var.put(item)
  1. Get the things in the variable
variable = shared_var.get()

There is a lot more you can do with queue, see the documentation.

DYD
  • 382
  • 2
  • 15
  • Thanks for taking the time to respond. I've updated the questions, didn't finish it before. I'm familiar with Queue, there is one that's built into concurrent, but i'm looking for a better solution. Manage seems like a great option, isn't there a similar one in concurrent? – Waleed Qutob Feb 28 '20 at 03:11
  • Oh sorry, should I delete the answer? – DYD Feb 28 '20 at 03:40
  • No need, it's fine, someone else could find it helpful. – Waleed Qutob Feb 28 '20 at 03:56