Python: Trying to restart script not working - python

Tried to restart my python script within itself.
Python 2.7.11
#!/usr/bin/python
# -*- coding: utf-8 -*-
import os
import sys
os.execv(__file__, sys.argv)
sys.exit()
Result:
Traceback (most recent call last):
File "...\foo.py", line 3, in <module>
os.execv(__file__, sys.argv)
OSError: [Errno 8] Exec format error
Another code:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import os
import sys
os.execv(sys.executable, [sys.executable] + sys.argv)
sys.exit()
Result:
C:\...\python.exe: can't open file 'C:\...\Math': [Errno 2] No such file or directory
The file's name is foo.py - it's in a folder name 'Math Project'
Codepage: 852, if necessary.

Your error message C:\...\python.exe suggests that you're running a Windows system.
Your first script fails because under Windows, os.execv() doesn't know how to handle Python scripts because the first line (#!/usr/bin/python) is not evaluated nor does it point to a valid Python interpreter on most Windows systems. In effect, os.execv() tries to execute a plain text file which happens to contain Python code, but the system doesn't know that.
Your second script fails to correctly retrieve the file name of your Python script foo.py. It's not clear to me why that happens, but the error message suggests that there might be a problem with the space in your directory name Math Project.
As a possible workaround, try replacing the line
os.execv(sys.executable, [sys.executable] + sys.argv)
by the following:
os.execv(sys.executable,
[sys.executable, os.path.join(sys.path[0], __file__)] + sys.argv[1:])
This line attempts to reconstruct the correct path to your Python script, and pass it as an argument to the Python interpreter.
As a side note: Keep in mind what your script is doing: it's unconditionally starting another instance of itself. This will result in an infinite loop, which will eventually bring down your system. Make sure that your real script contains an abort condition.
EDIT:
The problem lies, indeed, with the space in the path, and the workaround that I mentioned won't help. However, the subprocess module should take care of that. Use it like so:
import os
import sys
import subprocess
subprocess.call(["python", os.path.join(sys.path[0], __file__)] + sys.argv[1:])

Try this:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import os
import sys
os.execv(sys.executable, [sys.executable, '"' + sys.argv[0] + '"'] + sys.argv[1:])
Double quotation marks can help windows ignore that space.
It worked for me :)

Related

run a python script from another python script

i have a test script test.py inside which i am trying to run one more python script bexec.app(this is a python script). Actually test.py is just for my testing. The original script is a lengthy one and bexec.app is getting called inside in a command line.
I tried this
#!/usr/bin/python
import os, sys
os.path.insert(0, 'current bexec script path')
import bexec.app
But this does not work -
Traceback (most recent call last):
File "test", line 5, in <module>
import bexec.pphshaper
ImportError: No module named bexec.app
I donot want to change the bexec.app script to bexec_app.py because this follows some naming convention
bexec.app also has #!/usr/bin/python inside it.
how can i import my bexec script inside test.py
You seem to want to run your bexec, not import it. And if so, regular
os.system('current bexec script path')
should be sufficient
Dot means subpackage structure to python, but it's still possible with imp.
below is bexec.app sample file:
#!/usr/bin/python
a = 2
and this is how you can import it in your test.py file, look below for the code:
#!/usr/bin/python
import os, sys, imp
my_module = imp.load_source('my_module', 'bexec.app')
print (my_module.a)

Python RPi - File not found when running script from another script

I'm trying to run a python script from another python script on a Raspberry Pi 3 with Raspbian. I've been trying to find ways to do this for some hours and didn't find anything that worked. I've tried some ways but it either says that has not permission to execute the file or it can't find it. I don't know what I'm doing wrong. I need to run multiple instances of the other script through the main script in a new console (new processes) and keep them running (I don't expect them to return anything to the main script). Can anyone help me? Because with Windows it was really easy as the program was working fine until I tried to run it on Linux (with Windows, I used os.startfile).
In test.py:
print("test1")
input()
In main.py:
import os
import subprocess
print("main")
os.system("python test.py")
input()
In the console:
main
python: can't open file 'test.py': [Errno 2] No such file or directory
In main.py:
import os
import subprocess
print("main")
subprocess.Popen("python test.py",shell=True)
input()
In the console:
main
python: can't open file 'test.py': [Errno 2] No such file or directory
In main.py:
import os
import subprocess
print("main")
subprocess.call("python test.py",shell=True)
input()
In the console:
main
python: can't open file 'test.py': [Errno 2] No such file or directory
I tried more ways but I don't remember them. Maybe I'm doing something wrong?
EDIT: I can now run the scripts without any problems with os.chdir (thanks to J H). My problem now is that it prints test in the same console window as the main.py and I needed it to create another process for the test.py. Any solutions?
EDIT 2: Finally I could start a new processes of the test.py from the main.py! I used os.system('xdg-open "test.py"') to open test.py with the default application. Anyway thanks to J H, otherwise it would continue to say file not found.
Final main.py:
import os
print("main")
os.chdir('/home/pi/Desktop/')
os.system('xdg-open test.py')
input()
Thanks in advance!
Printing out os.getcwd() will help you to debug this.
Either supply a fully qualified pathname, /some/where/test.py, or use os.chdir('/some/where') before executing test.py.

Why can't the import command be found?

I am using the input function from fileinput module to accept script via pipes or input file Here is the minimum script:
finput.py
import fileinput
with fileinput.input() as f:
for line in f:
print(line)
After making this script executable, I run ls | ./finput.py and get unexpected error message
./finput.py: line 1: import: command not found
./finput.py: line 3: syntax error near unexpected token `('
./finput.py: line 3: `with fileinput.input() as f:'
The only fix I found is when I add #!/usr/bin/env/python3 before the import statement.
But this issue seems to be related only to the fileinput module. Since the following script worked well without a shebang:
fruit.py
import random
fruits = ["mango", "ananas", "apple"]
print(random.choice(fruits))
Now what am I missing? Why can't the import command be found since the shebang is not required in finput.py?
Your need to tell your OS that this is a Python program, otherwise, it's interpreted as a shell script (where the import command cannot be found).
Like you identified, this is done by using a shebang line:
#!/usr/bin/env python3
This is only needed if you are going to run your script like this: ./script.py, which tells your OS "run this executable". Doing so requires that your OS identify how it's supposed to run the program, and it relies on the shebang line for that (among other things).
However if you run python script.py (which I'm guessing you did for fruit.py), then Python does not ask your OS whether that is a Python program or not, so the shebang line doesn't matter.

Run python script from python using different python

I have a software that has python 2.5.5. I want to send a command that would start a script in python 2.7.5 and then proceed with the script.
I tried using
#!python2.7.5
and http://redsymbol.net/articles/env-and-python-scripts-version/
But I cant get it to work...
In my python 2.5.5 I can execute script as
execfile("c:/script/test.py")
The problem is that the 2.7.5 has a module comtypes + few other. I dont know how to install it for my 2.5.5 so I'm trying to start a separate script and run it under python27. Now another reason why I want it its because I want to take the load off program. I have 2 heavy tasks to perform. The second task is the one that need comptypes so sending it to external shell/app would do perfect trick. Is there a way to do it ?
I wish I could just type run("C:/Python27/python.exe % C:/script/test,py")
Thanks, bye.
Little update. I try to run
import os
os.system("\"C:\Python27\python.exe\" D:\test\runTest.py")
But I'm getting a quick pop up and close window saying that
Import Error : no module named site...
This works if I run from external shell but not from here :(
So I've tried another approach this time to add modules to python... in any case I run this :
import os
import sys
sys.path.append("C:/python27")
sys.path.append("C:/Python27/libs")
sys.path.append("C:/Python27/Lib")
sys.path.append("C:/Python27/Lib/logging")
sys.path.append("C:/Python27/Lib/site-packages")
sys.path.append("C:/Python27/Lib/ctypes")
sys.path.append("C:/Python27/DLLs")
import PyQt4
print PyQt4
import comtypes
import logging
but it crashes with C error...
Runtime Error :
Program: c:\Pr...
R6034
An application has made attempt to load the C runtime library incorectly.
blablabla....
How can I import it ? Maybe if I can import it I can run it directly from my app rather than starting separate python...
Traceback (most recent call last):
File "<string>", line 18, in <module>
File "C:\Python27\Lib\site-packages\comtypes\__init__.py", line 22, in <module>
from ctypes import *
File "C:\Python27\Lib\ctypes\__init__.py", line 10, in <module>
from _ctypes import Union, Structure, Array
ImportError: DLL load failed: A dynamic link library (DLL) initialization routine failed.
Another update to isseu
so I run now
import os
os.system("start cmd {D:\test\runTest.py}")
now this works and he open CMD with c:\Python27 as directory but he dont run the file... any hitns how to fix it?
Use "raw" strings so that you don't need to escape as much; I think the backslashes are what was breaking your code since backslash is considered an escape character except in raw strings.
Also, use the subprocess module. It makes it easy to avoid manually making a safe command string (the module takes care of that for you). All you need to do is pass it a list of arguments.
Your code would then look something like this:
import subprocess
proc = subprocess.Popen([r"C:\Python27\python.exe", r"D:\test\runTest.py"])
# then either do this
proc.wait() # wait until the process finishes
# or this
while True:
# NOTE: do something else here
# poll the process until it is done
if proc.poll() is not None:
break # break out of loop
See subprocess docs for Python 2 here. Be sure to check if a feature was added after Python 2.5 (the 2.5 docs aren't available online anymore AFAIK).
UPDATE:
I just noticed that you tried to use the Python 2.7 libraries and modules in your 2.5 code. This probably won't work due to new features added after 2.5. But it got me thinking how you might be able to make 2.7 work.
It may be that your Python2.7 install can't find its libraries; this is probably why you get the error Import Error : no module named site. You can do something like the above and modify the PYTHONPATH environment variable before starting the subprocess, like this:
import os
import subprocess
paths = [r"C:\python27", r"C:\python27\libs", r"C:\python27\Lib\site-packages", r"C:\python27\DLLs"]
paths += os.environ.get('PYTHONPATH', '').split(os.pathsep)
env27 = dict(os.environ)
env27['PYTHONPATH'] = os.pathsep.join(paths)
proc = subprocess.Popen([r"C:\Python27\python.exe", r"D:\test\runTest.py"], env=env27)

Why does importing subprocess change my output?

I noticed the following using Python 2.5.2 (does not occur using 2.7):
#!/usr/bin/python
import sys
for line in sys.stdin:
print line,
Output:
$ echo -e "one\ntwo\nthree" | python test.py
$ one
$ two
$ three
as expected. However, if I import subprocess to the this script:
#!/usr/bin/python
import sys
import subprocess
for line in sys.stdin:
print line,
Output:
$ echo -e "one\ntwo\nthree" | python test.py
$ two
$ three
What happened to the first line of output?
Update:
I think I may have discovered the root of the problem. I had a file named time.py in my cwd. A time.pyc is being created every time I run the script with subprocess imported, suggesting that ./time.py is also being imported. The script runs normally if I delete the .pyc and time.py files; however, there is still the question of why a subprocess import would cause ./time.py to be imported as well?
I have narrowed it down even further to the exact line in time.py that causes the strange behaviour. I have stripped down the working dir and file content to just that which affects the output:
test.py
#!/usr/bin/python
import sys
import subprocess
for line in sys.stdin:
print line,
time.py
#!/usr/bin/python
import sys
for line in sys.stdin:
hour = re.search(r'\b([0-9]{2}):', line).group(1)
Running test.py with any kind of input results in the first line of output being omitted and time.pyc being created.
Sounds like your local time.py will be imported instead of the global time module. You might want to rename it, or at least start checking if it was run as a script or imported as a module.
This will prove it for you if you want to test it.
#!/usr/bin/python
import sys
# Test that script was run directly
if __name__=='__main__':
for line in sys.stdin:
hour = re.search(r'\b([0-9]{2}):', line).group(1)
else:
print 'Imported local time.py instead of global time module!'
sys.exit(1)
print line, before 2.7 did not put out a newline so it overwrote the first line. Lose the comma and the result will be the same.

Categories