0

What I'm wanting to do is save files written by the executable I'm running to a Dropbox folder. The files are saved at random times, so I can't use a timer.

The only ways I know of executing files are non-blocking, and when I run the functions, they simply just execute and continue (for example, using subprocess to run a start command with the argument being the executable).

I can't modify the executable, I can only run it.

Here's what I've tried so far: I have looked up the question and haven't found anything. The only way I know of executing something with python is using the suprocess' call function and the Popen function, and using the start command to execute the executable. But that is still non-blocking, and continues after the executable has started, not ended.

martineau
  • 119,623
  • 25
  • 170
  • 301
CatCraftYT
  • 103
  • 8
  • 2
    Can you share what you have tried so far? – Iain Shelvington Dec 29 '19 at 23:13
  • 1
    I don't understand the question, perhaps you could rephrase / add additional info? how many programs are there involved? There seems to be files written by **the program** and then you talk about about using `subprocess` and then you talk about not being able to change **the executable** Well I don't understand and chances might be some others neither. Rephrsing / additional info might help – gelonida Dec 29 '19 at 23:35
  • Sorry - I should clarify. The executable (which is completely seperate from the python script) writes a file, then the python script copies those files to the Dropbox folder once the executable has fully stopped. I'll edit the question to clarify that. – CatCraftYT Dec 29 '19 at 23:39
  • 1
    Please look also at my answer below. Perhaps you might also explain, why you use `start` and not just a simple `subprocess.call([executable_name])`? The executable, that you want to call, is this a graphical application or a console application? What happens if you type the executable name in a cmd window. Does the `cmd` window block or do you immidiately get a new prompt and the program executes non blockingly? – gelonida Dec 29 '19 at 23:46
  • When I use `subprocess.call(['executable_name'])` it just returns `0` and continues. `run` and `Popen` all do the same thing. – CatCraftYT Dec 30 '19 at 00:03

4 Answers4

1

I think you want something like the following;

# using module subprocess to pass arguments to and from an
# external program:
import subprocess
# put in the corresponding strings for
# "mycmd" --> external program name
# "myarg" --> arg for external program
# several args can be in the list ["mycmd", "myarg1", "myarg2"]
# might need to change bufsize
p = subprocess.Popen(["mycmd", "myarg"], bufsize=2048, shell=True,
    stdin=subprocess.PIPE, stdout=subprocess.PIPE, close_fds=True)
# allow external program to work
p.wait()
# read the result to a string
result_str = p.stdout.read()
Madison Courto
  • 1,231
  • 13
  • 25
0

Here I just answer to the title of the question. I did not understand the detailed description.

subprocess.call() is blocking.

However using start under Windows blocks only for the time needed to start a program and will not wait for the program to finish (as mentioned in the documentation of start)

You might look at start /wait (e.g. mentioned in CALL command vs. START with /WAIT option )

gelonida
  • 5,327
  • 2
  • 23
  • 41
0

The child process needs to communicate somehow when it has finished writing to the file so that your parent process can start reading the file.

If the child process terminates when it has finished writing file, you can wait() to block until the child process finishes. In the simpler case, you can use .run() method. In more complicated scenarios, you may need to use the select() system call if you want to wait for multiple processes simultaneously.

If your child process doesn't terminate, then you need to detect completed writing some other way. You may be able to do so by parsing the standard output/error of the command for keywords that indicates completion, or you can poll the filesystem at the expected file location and watch the directory until the new file appears or hasn't been written to for x seconds.

Lie Ryan
  • 62,238
  • 13
  • 100
  • 144
  • `subprocess.Popen(['executable.exe']).wait()` simply returns `0`. It is only one process, and the executable does terminate when the user quits. Also, the executable isn't just a writing files and stopping, it does other things and then writes files when the user deliberately saves. – CatCraftYT Dec 30 '19 at 00:27
  • @CatCraftYT: if wait() or these calls returns zero, that means that the child process has terminated successfully. If the file hadn't appeared when the child process completion, there's two things that could be happening. Either the child process spawned another grandchild process to run the real program that created the file and daemonized/detached the grandchild, or it sent a message to a service that performed the operation. Without any details on what the child process does, we can't really help you further than that. – Lie Ryan Dec 30 '19 at 02:36
0

I've gone with this approach, it's not exactly what I wanted but it'll do:

import subprocess
import time

load_files()
subprocess.run(['executable.exe'])
time.sleep(5)

while b'executable.exe' in subprocess.check_output('tasklist'):
    time.sleep(1)

save_files()
CatCraftYT
  • 103
  • 8