-1

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 -:

  1. 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, ...]

  2. Now I convert the above list into a dictionary with two keys -:

    • The first key is 'name' which has the value as the name of the command.
    • The second key is 'args' which is a concatenated string value (of all the other list items except the first list item from the first step).

    So it becomes -:

    command_input = {'name' : 'python', 'args' = 'test.py'} # i.e. {'name': cmd, 'args': concat_str_of_args}
    
  3. 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:

Output of test.py using my script

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'
typedecker
  • 1,351
  • 2
  • 13
  • 25
  • 1
    Please don't post images of code, data, or Tracebacks. Copy and paste it as text then format it as code (select it and type `ctrl-k`) ... [Discourage screenshots of code and/or errors](https://meta.stackoverflow.com/questions/303812/discourage-screenshots-of-code-and-or-errors) – wwii Dec 05 '20 at 15:36
  • 1
    Please include the complete `test.py` with your [mre]. Or enough or it that we can copy and paste into an editor and reproduce your results. – wwii Dec 05 '20 at 15:40
  • Actually I would have pasted the traceback but it is a gui I have made on which the output is showing where the text is displayed in a tkinter listbox and not selectable. – typedecker Dec 05 '20 at 15:47
  • Also the complete code of test.py has been given theres only 1 line – typedecker Dec 05 '20 at 15:48
  • Also thanks for the info about the proper way of posting tracebacks I'll surely keep in mind next time I post a question. Unfortunately in here the traceback cannot be copied exactly from the gui element and thus I have provided a screenshot. – typedecker Dec 05 '20 at 15:56
  • Your question does not show the code that uses `subprocess` to run the script. Please add that. – martineau Dec 05 '20 at 15:59
  • Its there the result = subprocess.run line is the one – typedecker Dec 05 '20 at 16:03
  • os.environ["PYTHONUNBUFFERED"] = "1" print('BLAHDEHDEUFUFH', [command_output['args'][0]], ' '.join(command_output['args'][1 : ]), ' '.join(command_output['args'][1 : ]).encode('utf-8'), 'FI4IFJ4IUFH4UFH4F') 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:') – typedecker Dec 05 '20 at 16:07
  • This part of the code is there in the question too and is having the last line as subprocess code – typedecker Dec 05 '20 at 16:07
  • So `test.py b'test.py' FI4IFJ4IUFH4UFH4F` **is** `' '.join(command_output['args'][1 : ]).encode('utf-8')`?? – wwii Dec 05 '20 at 16:10
  • No its the result of the print statement at the top – typedecker Dec 05 '20 at 16:13
  • print('BLAHDEHDEUFUFH', [command_output['args'][0]], ' '.join(command_output['args'][1 : ]), ' '.join(command_output['args'][1 : ]).encode('utf-8'), 'FI4IFJ4IUFH4UFH4F') its output of this line – typedecker Dec 05 '20 at 16:15
  • If `command_output = {'args':['python','test.py', b'test.py', 'FI4IFJ4IUFH4UFH4F']}` then I get - `TypeError: sequence item 1: expected str instance, bytes found` for `' '.join(command_output['args'][1 : ]).encode('utf-8')` – wwii Dec 05 '20 at 16:19
  • Voting to close for lacking an [mre] - I, at least, cannot piece together what you are executing to cause your problem. – wwii Dec 05 '20 at 16:20
  • Kindly read the question description carefully before voting all info regarding the problem has been provided. – typedecker Dec 05 '20 at 16:43
  • The print command is not just printing command_output's element rather also the encoded and decoded part, perhaps you are not calmly and carefully reading the code I've given or else it all makes sense except the error I've got. We can talk further in chat. – typedecker Dec 05 '20 at 16:45
  • The .encode func has been used by me to encode it into bytes in the print statement – typedecker Dec 05 '20 at 16:46
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/225563/discussion-between-wwii-and-matrix-programmer). – wwii Dec 05 '20 at 16:48

1 Answers1

1

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:')
wwii
  • 23,232
  • 7
  • 37
  • 77
  • The file itself resides in the C: directory only – typedecker Dec 05 '20 at 18:32
  • Thx, I got it to work now I guess it was the cwd command that was not working and the current working directory was not changing thus it was picking up a local file and not the one in C: drive despite passing cwd arg as C: but as you mentioned writing full path makes it work! Thx – typedecker Dec 06 '20 at 08:12
  • Now, if you think the question is understandable and can be useful to others in need please vote for reopening of the question. – typedecker May 02 '21 at 13:09
  • @MatrixProgrammer: Sure ... but your question may need more detail - when I read your current edit I was still confused and had to review our chat discussion - which I based my answer on. Feel free to retract the *acceptance* if that is possible. If you came up with your own solution: [Can I answer my own question?](https://stackoverflow.com/help/self-answer) – wwii May 02 '21 at 14:38
  • Kindly review the question once more and tell me if its suitable now to be opened up again. – typedecker Sep 18 '21 at 15:45