Trying to update command line inputs - python

My command line input looks like this:
python rerun_edit.py examples/Testing/config.yaml examples/Testing/0.blend examples/Testing/output
And my program looks like this:
import subprocess
import sys
import os
import pathlib
# this sets the amount of scenes
amount_of_scenes = 2
# this sets the amount of runs, which are performed
amount_of_runs = 5
# set the folder in which the run.py is located
rerun_folder = os.path.abspath(os.path.dirname(__file__))
blend_path = ["examples/Testing/0.blend"]
for scene_id in range(amount_of_scenes):
# the first one is the rerun.py script, the last is the output
used_arguments = str(sys.argv[1]) + (blend_path) + str(sys.argv[-1])
output_location = os.path.abspath(sys.argv[-1])
for run_id in range(amount_of_runs):
# in each run, the arguments are reused
cmd = ["python", os.path.join(rerun_folder, "run.py")]
cmd.extend(used_arguments)
# the only exception is the output, which gets changed for each run, so that the examples are not overwritten
#cmd.append(os.path.join(output_location, str(run_id)))
cmd.append(output_location)
print(" ".join(cmd))
# execute one BlenderProc run
subprocess.call(" ".join(cmd), shell=True)
print(used_arguments)
print(cmd)
#get the blend file
old_blend_file = str(scene_id) + ".blend"
new_blend_file = str(scene_id + 1) + ".blend"
blend_path = pathlib.Path(str(blend_path).replace(old_blend_file, new_blend_file))
print(blend_path)
It reads the command line inputs and executes a run.py program for a certain amount of runs.
After the runs I need to update the command line input to the following:
python rerun_edit.py examples/Testing/config.yaml examples/Testing/1.blend examples/Testing/output
So that it executes again for a certain amount of runs but with a different .blend file as input.
I tried to implement a for loop and adjust the paths name after the runs completed but I always getting an error saying:
used_arguments = str(sys.argv[1]) + (blend_path) + str(sys.argv[-1])
TypeError: can only concatenate str (not "list") to str
Can anyone help me out? Any help is highly appreciated.
Thank you very much :)

Here it is
import subprocess
import sys
import os
import pathlib
# this sets the amount of scenes
amount_of_scenes = 2
# this sets the amount of runs, which are performed
amount_of_runs = 5
# set the folder in which the run.py is located
rerun_folder = os.path.abspath(os.path.dirname(__file__))
blend_path = "examples/Testing/0.blend"
for scene_id in range(amount_of_scenes):
# the first one is the rerun.py script, the last is the output
used_arguments = [sys.argv[1], blend_path, sys.argv[-1]]
output_location = os.path.abspath(sys.argv[-1])
for run_id in range(amount_of_runs):
# in each run, the arguments are reused
cmd = ["python", os.path.join(rerun_folder, "run.py")]
cmd += used_arguments
# the only exception is the output, which gets changed for each run, so that the examples are not overwritten
#cmd.append(os.path.join(output_location, str(run_id)))
cmd.append(output_location)
print(" ".join(cmd))
# execute one BlenderProc run
subprocess.call(" ".join(cmd), shell=True)
print(used_arguments)
print(cmd)
blend_path = pathlib.Path(blend_path.replace(("%d.blend" % scene_id), ("%d.blend" % (scene_id + 1))))
print(blend_path)
Please check if it works and comment me if there are any errors

Related

Endless loop when importing a variable from another file in Python

I have a file called main.py and based on the user input I want to run the code either from file export.py, either from file import.py. This is how my code from main.py looks:
print("Hi, " + os.getlogin() + "!")
print("Extracting filenames...")
path = input('Tell me the path!\n')
filenames = [x for x in os.listdir(path)]
ID = [f for f in filenames if re.search("(?<=ID)(\d+)", f)]
filestxt = "Files.txt"
idtxt = "ID.txt"
PathFiles = os.path.join(path, filestxt)
PathID = os.path.join(path, idtxt)
file = open(PathFiles, "w+")
file.write('\n'.join(ID))
file.close()
with open(PathID, 'w') as f:
for item in ID:
list = re.findall("(?<=ID)(\d+)", item)
string = ('\n'.join(list))
f.write("%s\n" % string)
key = input("Export or Import(e/i)?:")
if key == 'e':
os.system('python export.py')
When I am hitting the 'e' button Python is running the code from export.py, but when it gets to the line
from main import PathID
instead of importing the variable which I need for the following function
with open(PathID) as f:
for line in f:
...
the code from main.py is running again and again from the beginning and I get the following lines in the console:
"Hi, " + os.getlogin() + "!"
"Extracting filenames..."
'Tell me the path!\n'
"Export or Import(e/i)?:"
All I want in export.py is to tell Python to read the ID.txt file from the path I have specified in the main.py file.
How can I call the function from main.py in export.py without getting this endless loop?
Try to use
if __name__ == '__main__':
before
key = input ("Export or Import (e / i) ?:")
if key == 'e':
os.system ('python export.py')
or before any code that should always be executed at startup.
To expand on Jossnix's answer:
When you execute os.system('python export.py'), you're launching a separate Python interpreter process.
When you execute from main import PathID within export.py, all of the code in main.py is run, and then, once it's finished running, the control flow is returned to export.py and it has access to PathID. The problem is that, as it stands, your main.py asks for user input. So, your main.py is stuck waiting for user input - you have to provide the input again to this new Python interpreter session! Hence, export.py is stuck while trying to import main.
Jossnix's solution works because it ensures that the user input component of main.py does not get run if main.py is being imported from another module, but will be run if main.py is executed as the main script.
I think you should get rid of the os.system('python export.py') line entirely. It's wasteful: you're launching a completely separate Python interpreter session and the print messages in main.py get run again (this is pretty confusing for the end-user!). I'd say you're better off having whatever code you want to run if the user enters the key 'e' wrapped in a function, and then run this function directly from main.py (if the user has indeed entered 'e'). You could do this: Create such a function (f) in export.py, taking a PathID argument. Then, within main.py, from export import f. Finally, if the user entered 'e', run f(PathID, ...).

Not able to send input argument values using subprocess Python Windows 10

I am running a main script on windows 10 that calls another script called audioplayer.py using the subprocess module in python.
I want to send some input arguments when calling the audioplayer.py. So I wrote the main script as follows:
The following is the main script:
from subprocess import call
call(["python", "C:/Users/Jeff/Documents/audioplayer.py", "hey.wav"])
The following is my audioplayer.py:
"""OpenAL playback example."""
import os, sys, time
from openal.audio import SoundSink, SoundSource
from openal.loaders import load_wav_file
if len (sys.argv) < 2:
print ("Usage: %s wavefile" % os.path.basename(sys.argv[0]))
print (" Using an example wav file...")
dirname = os.path.dirname(__file__)
fname = os.path.join(dirname, "default.wav")
else:
fname = sys.argv[1]
sink = SoundSink()
sink.activate()
source = SoundSource(position=[10, 0, 0])
source.looping = True
data = load_wav_file(fname)
source.queue(data)
sink.play(source)
source.position = [source.position[0], source.position[1], source.position[2]]
sink.update()
time.sleep(2)
print("playing at %r" % source.position)
But I keep getting the following error even though the file does exist in the same directory as audioplayer.py
FileNotFoundError: [Errno 2] No such file or directory: 'hey.wav'
If I remove the hey.wav in the main script, it runs fine. It just doesn't seem to take any arguments.
try this:
call(["python", "C:/Users/Jeff/Documents/audioplayer.py", "C:/Users/Jeff/Documents/hey.wav"])
When you run the last one, the dir is the same with the main.py instead of the audioplayer.py.

Calling a sub process after for loop is completed in python

I have python script like below. In this script, I am collecting stdout and stderr of the script in a file and storing in Linux.
In this script, I am running the function path_finder in a loop over input_file
In this script, I am using subprocess to move data in Linux to a different location.
I want this subprocess call to run after finishing the loop but instead, it runs when the loop runs for the first time and when the second time the loop runs it throws an error which is expected. As the file is present it throws an error.
#!/usr/bin/python
import os
import sys
import traceback
import subprocess
def path_finder(
table,
mysql_user,
user,
dir,
):
day = datetime.now().strftime('%Y-%m-%d')
month = datetime.now().strftime('%Y-%m')
Linux_path = '/data/logging/{}'.format(input_file)
New_path = '/user/{}/{}/logging/{}/{}/{}'.format(user,dir,mysql_user,month,day)
subprocess.call(["rm", Linux_path])
so = se = open('/data/logging/{}'.format(input_file), 'a',
0)
#re-open stdout without buffering
sys.stdout = os.fdopen(sys.stdout.fileno(), 'a', 0)
# redirect stdout and stderr to the log file opened above
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())
### CODE:
Do something
### if errors the print traceback
### repeat the same for every table in input file
## Execute below statement after for loop completed
subprocess.call(["cp", Linux_path, New_path])
if len(sys.argv) != 5:
print 'Invalid number of args......'
exit()
input_file = sys.argv[1]
mysql_user = sys.argv[2]
user = sys.argv[3]
dir = sys.argv[4]
input = open("{}.format(input_file)", "r")
for table in input:
path_finder(
table,
mysql_user,
user,
dir,
)
sc.stop()
print
How can I change my script so that the sub process call will run after the for loop is done?
I don't see what the problem is. The statement you want to execute last is currently present in the function 'path_finder' which is why it is running every time.
To make this run only once and after the for loop is finished, put the statement after it.
for table in input:
path_finder(
table,
mysql_user,
user,
dir,
)
subprocess.call(["cp", Linux_path, New_path])
This should do it.

How to Get Variable from another .py

I have two .py programme. I call second .py program , the second program solves a problem . So ı want to get that solution to first one and use . for example:
1.py:
call 2.py
y= x+2
2.py:
x = 2+2
You need to import the .py file into another file
Running it in OS does not get the variable in your new file
Use
from module import function
You can then call the function from this new file and print the value that it returns
Use the subprocess module and create a pipe. Then you can pickle the variable and send it through the pipe (see documentation of subprocess).
Here is an example:
module for communication communicate.py:
import sys
import subprocess as sp
import cPickle
BEGIN = 'pickle_begin'
def send_and_exit(x):
sys.stdout.write(BEGIN + cPickle.dumps(x))
sys.stdout.flush()
sys.exit(0)
def execute_and_receive(filename):
p = sp.Popen(["python", filename], stdout=sp.PIPE)
(out, err) = p.communicate()
return cPickle.loads(out[out.find(BEGIN) + len(BEGIN):])
1.py:
from communicate import *
x = execute_and_receive("2.py")
y = x + 2
2.py:
from communicate import *
x = 2 + 2
send_and_exit(x)
To make sure, you start unpickling at the correct point of the stdout stream I recommend to set a marker, like I did with the BEGIN string. Probably there are more elegant solutions, if so, I'm interested as well.

python or bash script that does something when there is no response(output)

There is an external program A.
I want to write a script that does some action if the called external program A does not bring up any output(stout).
How is this possible in bash or python?
You can use the subprocess module which allows you to execute system calls and store its output in variables which can be used later on.
#!/usr/bin/python
import subprocess as sub
ur_call = '<your system call here>'
p = sub.Popen(ur_call, stdout=sub.PIPE,stderr=sub.PIPE)
output, errors = p.communicate()
if len(output) == 0 and len(errors) == 0:
pass # Do something
In a Bash-script, you could redirect the output to a file, and if the length of the file is zero then there was no output.
If the script that sometimes gives output is no.sh then you can do this in Python:
import os
x = os.popen("./no.sh")
y = x.read()
if y:
print "Got output"

Categories

Resources