1

I have a Python file, which I want to open, keep open for 5 seconds, and then close it, and then repeat. I am using Python Subprocess for this, using the following code:

import subprocess
import time
import sys

p = subprocess.Popen("pagekite.py")
time.sleep(4)
p.terminate()

However, it gives me the following error:

Traceback (most recent call last):
File "C:/Users/ozark/Desktop/Savir/Programming/Choonka/closetry.py", line 5, in <module>
p = subprocess.Popen("pagekite.py")
File "C:\Users\ozark\AppData\Local\Programs\Python\Python38-32\lib\subprocess.py", line 854, in 
__init__
self._execute_child(args, executable, preexec_fn, close_fds,
File "C:\Users\ozark\AppData\Local\Programs\Python\Python38-32\lib\subprocess.py", line 1307, in 
_execute_child
hp, ht, pid, tid = _winapi.CreateProcess(executable, args,
OSError: [WinError 193] %1 is not a valid Win32 application

It seems only executables can be opened using this method? Then how do I do the same thing for a Python file? Any help will be appreciated. Thanks in advance.

MODIFICATIONS: I am now using subprocess.call('start pagekite.py', shell=True). How do I terminate this? Thanks.

7
  • You'd need to run the python interpreter, and give your script as an argument. As the error says, you can't directly run a Python script. Are you sure what you're trying to do can't be achieved through just importing the other script though? Commented May 5, 2021 at 13:41
  • Yes, importing the script doesn't work... that's why I'm using this method. Commented May 5, 2021 at 13:42
  • If Python cannot import the script, are you sure it can execute it? Fixing it so you can import it is usually the best solution. Commented May 5, 2021 at 13:45
  • Yes, the script (a third party Python file) can be executed, but only by double-clicking the file, importing doesn't work. Commented May 5, 2021 at 13:46
  • Windows can be configured to supply python before the script name when you try to execute it, but this is less commonly done than on Unix-like platforms; the simple and portable solution is to spell out python. Commented May 5, 2021 at 13:47

2 Answers 2

0

I had this question myself! It's actually much easier than it seems! You need some modules for this though, and there will be some wait time to start the Python file, but it works great as an automated process.

You don't actually need Psutil for something simple like this. Refer to the following code, and you'll figure something or the other out:

import subprocess
import time
import sys
import os

while True:
  subprocess.call('start pagekite.py', shell=True)
  time.sleep(32)
  os.system("TASKKILL /F /IM py.exe")

Basically, Python scripts actually run through C:\WINDOWS\py.exe, and if you're able to close py.exe, you should be good! For this, just close py.exe using os.system("TASKKILL /F /IM py.exe")

Using a while loop, you can run the code forever, thus opening "pagekite.py", keeping it open for at least 20 seconds (I figured this would be the load time for such a script - 5 seconds isn't enough), and then closing "py.exe", which would in turn close "pagekite.py". Afterwards, the whole thing occurs again.

You could change the "32" back to "5", but "pagekite.py" probably won't have enough time to load, so I would keep it at "32", unless your server manages a lot of traffic.

I hope this helps you, and happy coding!

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks so much, it actually worked, and I'm keeping it at 32, you're right, 5 seconds wasn't enough time. Thank you again!!!!!!!!
0

I've used

subprocess.call('start python C:\your\path\to\your\file.py', shell=True)

That'll launch into a separate window, and close when complete.

You never mentioned whether you need to get data from the subprocess back to your calling process. If you do, and want it in DRAM, the above won't really work (to my knowledge). You need pipes set up. (obviously of course, you could pass back via files written to HD, or via shared memory server like memcache)

edit: To kill the child after 5 seconds (assuming nominal runtime is > 5 seconds), you need the PID.

#In child
import os
pid = os.getpid()

Killing it,

#In parent
import psutil
psutil.Process(pid).terminate() 

Getting the info from child to parent is not something I've done in memory before.

#In parent  - note change from original proposal
subProc = subprocess.open('python', 'C:\your\path\to\your\file.py', stdout=sp.PIPE shell=True)
pipeOutput = subProc.stdout.read()

#In child
def main():
    #First duty is to report the PID back up to parent
    import os, sys
    pid = os.getpid()
    sys.stdout.write(pid)
    sys.sdout.flush()  #this *should* populate the pipe at this point
    
    #Then insert your existing functional code here

Should have worked... but a quick test and I'm not convinced my return is coherent.

edit2: From here: https://docs.python.org/3/library/subprocess.html#subprocess.run

Could try this approach:

#All in parent
proc = subprocess.Popen(...)
try:
    outs, errs = proc.communicate(timeout=5)
except TimeoutExpired:
    proc.kill()
    outs, errs = proc.communicate()

10 Comments

Hi, thanks, that works to open the script, and close it when it's done, but I want to close it after 5 seconds, so how do I close it after a certain period of time?
Look into psutil and kill the process ID I'd guess
Do you want to close it before it finishes or do you want to leave it open after it finishes so total shell time is 5 seconds? Or do you want it to hang around and wait for data? Depending on why you want the 5sec window will affect the solution - and it'll likely reside in the child process rather than parent.
Peter is correct, if you can get the PID, you can indeed use psutil to kill it: psutil.Process(pid).terminate()
Hi, I want to close it before it finishes, I'm running a server, and I need the script to open for five seconds and then close.
|