0

I am trying to create a GUI in tkinter. The Gui is basically for Mcp23017. I am trying to configure the input and output pins so that the user could change them according to their choice.. There is also an option to make the inputs/outputs high or low..

Now I am trying to read a pin using 'i2cget'(using a seperate function).. I need to display the output of this subprocess call into a label on the gui..

This is what my code looks like:

def read_p22():
   output = subprocess.call(['i2cget -y 0x20 0x12 0xFD'],shell=True)
   x=print (output)
   Label(tableframe,textvariable=x).grid(row=2,column=20)
   root.after(5000, read_p22)

When this function excutes(by pressing a button), however it prints a value '1' on the python shell alternatly when I press the button... I dont know how to redirect the output to the label.. Could somebody suggest something?

Update:: On executing the suggested commands:

process = subprocess.Popen(['i2cget -y 0x20 0x12 0xFD'], stdout=PIPE,      stderr=PIPE, shell=True)
output, code = process.communicate()

I printed the 'output' and 'process' and they gave me the follwing respectivley:

b'' <subprocess.Popen object at 0x00000000035CB2B0>

Since nothing is connected to the pin I expect it to return a value of '0'.. I don't know what is the b'' it is giving me ...

Any advice is really appreciated..

Kind Regards, Namita.

jfs
  • 399,953
  • 195
  • 994
  • 1,670
Goldengirl
  • 957
  • 4
  • 10
  • 30
  • the b'' you are getting returned is pythons was of displaying an empty byte string, as it does not have a specific encoding with it – James Kent Apr 01 '15 at 12:35
  • @James Kent: Thank you for clarifying that for me..:) But shouldn't it give me a '0' instead? Or will it give a 0 only when I actually connect something? And also this (b'') still appears on the shell not in the GUI. Is there a way I could put it on the GUI? – Goldengirl Apr 01 '15 at 12:39
  • if you don't know what `b''` is then you should learn some Python first before trying to combine `tkinter` and `subprocess`. If you already know some other programming language then [read the official Python tutorial](https://docs.python.org/3/tutorial/) otherwise [start with Python for Non-Programmers](https://wiki.python.org/moin/BeginnersGuide/NonProgrammers) – jfs Apr 01 '15 at 22:32

2 Answers2

1

What you have is the return code, not the output.

From subprocess.call docs:

Run the command described by args. Wait for command to complete, then return the returncode attribute.

Instead, use subprocess.Popen to open a process, subprocess.PIPE to pipe the output to you, and Popen.communicate get the output:

process = subprocess.Popen(['i2cget -y 0x20 0x12 0xFD'], stdout=PIPE, stderr=PIPE, shell=True)
output, code = process.communicate()
# do stuff with output...
Reut Sharabani
  • 30,449
  • 6
  • 70
  • 88
  • Thank You for that quick response.. :) I tried what you said.. It gives me a error saying output, code = process.communicate() NameError: name 'process' is not defined . What am I doing wrong? – Goldengirl Apr 01 '15 at 11:39
  • @NamitaRaju if it's not working don't accept the answer. I fixed it by renaming the `Popen` object to `process`. – Reut Sharabani Apr 01 '15 at 11:40
  • I am sorry, but I did not understand what you meant by renaming the Popen object.. – Goldengirl Apr 01 '15 at 11:44
  • @NamitaRaju I've fixed it in the answer itself. The `Popen` object was named `output` (first line), and referred to by `process` (second line). – Reut Sharabani Apr 01 '15 at 11:44
  • What does `i2cget -y 0x20 0x12 0xFD` return? Update your question to include the output of the command and what you expect to appear. Try and print `output` to see what it contains. – Reut Sharabani Apr 01 '15 at 11:51
  • I updated my question.. Could you please be kind enough to have a look – Goldengirl Apr 01 '15 at 12:06
  • the 2nd variable is not `code`; it is `stderr_output`. Don't use a list with `shell=True`; just pass a string (the shell command) as is. Anyway `shell=True` is probably unnecessary here. – jfs Apr 01 '15 at 19:19
  • @J.F.Sebastian well, he used it to use `/bin/sh`. Maybe it is necessary. – Reut Sharabani Apr 01 '15 at 20:32
  • OP doesn't know what `b''` is in Python. It suggests that `shell=True` is most likely unnecessary here. – jfs Apr 03 '15 at 06:21
1

There are multiple things wrong in your code. You should split your problem into tiny tiny subtasks and complete each task independently.

1. Get output from a subprocess as a string variable in Python

subprocess.call() returns an integer (exit status), not string (the output) -- start Python REPL and try to run any command via subprocess and see for yourself: it should help you to understand what is happening in addition to reading the linked documentation.

You could use subprocess.check_output(), to get the output if you don't mind blocking your GUI thread -- nothing will respond until the subprocess returns.

Otherwise (if i2cget does not return in an instant, always), you could do it asynchroniously using threads or .createfilehandler() method.

2. Learn why x = print(output) is useless in Python

It is SyntaxError in Python 2 by default. Otherwise print() function always returns None i.e., you could have written x = None (except that output is printed to stdout as a side-effect).

3. Update text in a Label

Community
  • 1
  • 1
jfs
  • 399,953
  • 195
  • 994
  • 1,670
  • @JFSebastian : Thank you for all the tips.. I am a beginner in python and thus the 'not so elegant' code.. I will try and use the suggestions you gave me.. _However regarding the 'subprocess.check_output', whenevr I try to use it and run it in my python 3 in win7 system it gives me the error saying `FileNotFoundError: [WinError 2] The system cannot find the file specified `.. I don't really understand why.. Could you suggest something? – Goldengirl Apr 07 '15 at 08:14
  • @NamitaRaju: make sure you can run the command that you pass to `check_output()` from the command-line (if you don't know what "the command-line" is -- [learn it first](http://learnpythonthehardway.org/book/appendixa.html)). If it works from the command line but fails with `check_output()` then create a [minimal but complete code example](http://stackoverflow.com/help/mcve) and [post it as a separate question](http://stackoverflow.com/questions/ask). – jfs Apr 07 '15 at 08:53
  • @J.Fsebastian: Sorry I forgot to mention that I tried to run it from the command line too. But it gives me the same error. – Goldengirl Apr 07 '15 at 09:06
  • @NamitaRaju: I meant, run the child process manually (without Python) -- so that you would know how the correct command should look like. – jfs Apr 07 '15 at 20:58