1

I have created a python interface for the yad program. What the code basically does is that, it generates a string which gets passed to the yad program using pythons subprocess and/or pexpect module and executes it

Now, Im facing a weird bug where I am trying to display a simple [multi]progress bar and update the bar with a certain value like this:

import yad, time

yad = yad.YAD()

x = yad.Progress(autoclose=True) # yad.MultiProgress(autoclose=True)

for i in range(0,105,5):
  print(i)
  x(i,msg=str(i)+"% done")
  time.sleep(0.5)

The problem is that, in python 2.7, it works fine(updates the bar, and closes after wards), But when it comes to python 3.4, it does not work(shows the bar, but does not update, even though the for loop prints the numbers).

Im trying to figure out what the problem is with my interface. The functions are written in such a way that, it should update the bar, but for some reason its not working in python 3.4.

Kindly help me with this problem. I am not able to figure out where the bug is.

Edit : x is a function that is returned as output when we call the yad.Progress(). Using the x, we can write some standard input to the yad. The shell equivalent of the code would be something like this:

yad --progress --auto-close
> 5
> # 5% done 
...
dvenkatsagar
  • 936
  • 7
  • 22
  • Try sending a bytes object instead of a string, `msg.encode()` – cdarke Feb 14 '16 at 08:06
  • I dont understand.... Can you please give an example...?? – dvenkatsagar Feb 14 '16 at 08:07
  • Python 3 strings are multi-byte, Unicode. If the program requires single-byte strings, as Python 2 uses, then it won't be able to handle multi-byte. It is a common problem. the `str.encode()` method returns a bytes object, which is just like a Python 2 string. You might have to modify your module as well, depending on how you have written it. – cdarke Feb 14 '16 at 08:09
  • So you mean to say it would go something like this : `(str(i)+"% done").encode('utf-8')` ?? – dvenkatsagar Feb 14 '16 at 08:12
  • No, don't use the `utf-8`, default it. – cdarke Feb 14 '16 at 08:18
  • @cdarke Ok, I have tried that, but it is not working. still the same result. I know that it is a problem with the subprocess that is in the `Progress` function of the interface, there is a functionality to write the values to standard input. Now the question is, is that the correct way or not?? – dvenkatsagar Feb 14 '16 at 08:21
  • OK, it was just a guess. I can't think of anything else that might be Python 3 specific. I don't know enough about your interface to recommend the next step. – cdarke Feb 14 '16 at 08:25
  • 1
    Try adding a `p.stdin.flush()` after writing to the subprocess inside your module. You don't need to encode the text, because you use `universal_newlines=True` to create it, so it will accept unicode. – Thomas K Feb 17 '16 at 11:05
  • @ThomasK That worked.... thank you, but why do we need to do that? and why was it working fine in python2.7 even with out using the operation? Kindly give a clear answer for this and I will accept it. – dvenkatsagar Feb 17 '16 at 15:50
  • I've would do something like this http://stackoverflow.com/questions/30203228/unprint-a-line-on-the-console-in-python – kpie Feb 18 '16 at 04:03
  • I think that wouldn't help as my module uses subprocess to write to the `yad` program – dvenkatsagar Feb 18 '16 at 04:06
  • Not sure if it suits your use case, but I find [`tqdm`](https://pypi.python.org/pypi/tqdm) awesome to easily generate progress meters and bars – jorgeh Feb 18 '16 at 04:17
  • I think thats going off topic, I created a interface for a program that generates Gui components via the console and for that I need to write a standard input correct to the console, so that, that program will pick it up and update the gui accordingly. – dvenkatsagar Feb 18 '16 at 04:20

2 Answers2

2

Reposting as an answer:

Inside the wrapper module, call p.stdin.flush() after writing to the subprocess' stdin.

In Python 2, the default is to create Popen pipes without any buffering (the bufsize argument to subprocess.Popen defaults to 0). That means that any data you write is sent to the subprocess immediately. In Python 3, buffering is the default (bufsize defaults to -1, which means the default buffer size). So, for performance reasons, data is stored in memory until either the buffer fills up or you call flush.

Thomas K
  • 39,200
  • 7
  • 84
  • 86
0

You can use print("{}/100".format(k), "\r", end="") to unprint the last % and then print the updated progress.

kpie
  • 9,588
  • 5
  • 28
  • 50