I was recently using the subprocess module and it's run method to execute os commands through python only and get the output, since I was trying to make a custom command prompt in tkinter.
The way that command prompt handles commands I write into it is as follows -:
So when I write a command as input I split it from spaces for e.g.
INPUT: cmd exec python test.py
OUTPUT: ['cmd', 'exec', 'python', 'test.py'] # i.e. [cmd, arg1, arg2, ...]
Now I convert the above list into a dictionary with two keys -:
So it becomes -:
command_input = {'name' : 'python', 'args' = 'test.py'} # i.e. {'name': cmd, 'args': concat_str_of_args}
Now the dictionary made in the second process, is passed into a module, which interprets the command and it converts it into a normal command prompt command(NOTE: Previously the command was a custom one based on my own custom made syntax cmd exec command_prompt_command) in string form and returns it as a dict called command_output, with it's args as the list from step 1 ([cmd, arg1, arg2.....]).
Like so -:
command_output = my_module.convert_to_cmd_form(command_input) # returns a dictionary like so -: {'args' : ['python', 'test.py']}
Now I try executing a python script I made to test if this was working, The code for the test file is -:
# CODE FOR TEST FILE
print('This is a special test for the terminal cmd integration!')
And executing this file by IDLE I get the desired output with no error:
This is a special test for the interstellar terminal cmd integration!
While when I do the same with my custom command prompt which in the backend uses a special subprocess python script to run this test.py it gives a name error:
And I am not able to properly understand the reason for the same the code for executing scripts is somewhat like so:
os.environ["PYTHONUNBUFFERED"] = "1"
print([command_output['args'][0]], ' '.join(command_output['args'][1 : ]), ' '.join(command_output['args'][1 : ]).encode('utf-8'))
result = subprocess.run([command_output['args'][0]], input = ' '.join(command_output['args'][1 : ]).encode('utf-8'), stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell = True, env = os.environ, cwd = 'C:')
The print statement here was for debugging to check if all values were being parsed as expected.
['python'] test.py b'test.py'
my special subprocess python script to run this test.py it gives a name error:
Your mre from chat discussion:
import subprocess
command_output = {'args':['python',r'test.py'] }
result = subprocess.run([command_output['args'][0]],
input = ' '.join(command_output['args'][1 : ]).encode('utf-8'),
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
shell = True, env = os.environ, cwd = 'C:')
Include the full path to the file to alleviate the NameError: name \'test\' is not defined\r\n'
Exception.
command_output = {'args':['python',r'c:\full\path\test.py'] }
For the following solutions you would need to parse command_output
appropriately.
This form works
args = ['python', '-m', 'test']
other = subprocess.run([args,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
shell = True, env = os.environ, cwd = 'C:')
Using the input keyword argument, you need to send the python commands you would use if you were typing/executing from a python shell.
args = [b'python']
cmd = b'import test'
another = subprocess.run(args,
input = cmd,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
shell = True, env = os.environ, cwd = 'C:')
This one courtesy of this answer https://stackoverflow.com/a/1027739/2823755. Again you may need to include the full path to the file.
args = [b'python']
cmd = b'''exec(open("test.py").read())'''
another1 = subprocess.run(args,
input = cmd,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
shell = True, env = os.environ, cwd = 'C:')