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.

  • 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? – Carcigenicate May 05 '21 at 13:41
  • Yes, importing the script doesn't work... that's why I'm using this method. –  May 05 '21 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. – tripleee May 05 '21 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. –  May 05 '21 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`. – tripleee May 05 '21 at 13:47
  • Kind of. It shows me how to open the Python file, but not how to terminate it after 5 seconds. –  May 05 '21 at 14:37
  • Does anyone know how to close a program by its name? That would really help. –  May 05 '21 at 14:41

2 Answers2

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()
Amiga500
  • 1,258
  • 1
  • 6
  • 11
  • 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? –  May 05 '21 at 13:45
  • Look into `psutil` and kill the process ID I'd guess – Peter May 05 '21 at 13:48
  • 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. – Amiga500 May 05 '21 at 13:49
  • Peter is correct, if you can get the PID, you can indeed use psutil to kill it: psutil.Process(pid).terminate() – Amiga500 May 05 '21 at 13:49
  • 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. –  May 05 '21 at 13:50
  • Then you need to get the PID back from the child process. – Amiga500 May 05 '21 at 13:52
  • So what do I need to add to the script to terminate the process? –  May 05 '21 at 13:53
  • Ok, so this makes sense to me, is there a way to close a program by its name? –  May 05 '21 at 14:01
  • That didn't work for me. –  May 05 '21 at 14:28
  • Thanks for the answer, but I found the other answer more helpful. –  May 05 '21 at 17:58
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!

Jiji
  • 20
  • 1
  • 6
  • 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!!!!!!!! –  May 05 '21 at 17:56