Task : Using subprocess execute console utilities, more precisely, get a screenshot of the top utility output using imagemagick .

Did so. There is a screenshot.py :

 class Screenshot: file = '/tmp/screenshot.png' convert = 'convert -pointsize 20 -font Courier -fill black -background white label:@-' def get_shot(self, cmd): run_cmd = subprocess.Popen(cmd.split(' '), stdout=subprocess.PIPE) subprocess.check_output([self.convert.split(' '), '%s' % self.file], stdin=run_cmd.stdout) run_cmd.wait() return self.file def get_top(): top = Screenshot().get_shot('top -n1 -b') return top 

From run.py execute this case:

 ... import screenshot screenshot.get_top() ... 

In theory, if properly executed, screenshot.get_top() returns /tmp/screenshot.png . But in the course of performance nothing is returned. Experimentally (using print() :) ) I found out that execution stops at the subprocess.check_output() function. It seems that the arguments (commands) are passed to the function correctly, in the form of a list.

Ps. Prior to this, the same (similar, without OOP) code worked successfully. But I decided that it was time to master the PLO and tried to do it using the class. Perhaps this is stupid, but I'm wondering why this function does not work. What's the catch?

UPD . For example. A working version without classes, where the usual function is simply called:

 def get_screenshot(cmd): file = '/tmp/screenshot.png' convert = 'convert -pointsize 20 -font Courier -fill black -background white label:@-' try: run_cmd = subprocess.Popen(cmd.split(' '), stdout=subprocess.PIPE) subprocess.check_output([convert.split(' '), '%s' % file], stdin=run_cmd.stdout) run_cmd.wait() return file except Exception as e: return e get_screenshot('top -n1 -b') ... 

In this case, the top output through the pipe is successfully passed to stdin convert , and the function is executed.

  • echo надпись | convert label:@- файл.png command echo надпись | convert label:@- файл.png echo надпись | convert label:@- файл.png creates файл.png with an надпись . it returns nothing to stdout (well, except for help in case of incorrect parameters). You can do without the pipe: convert label:надпись файл.png - aleksandr barakin
  • You can, I know. I want python-way. - approximatenumber
  • because python does not load the program, but its behavior is unlikely to change: it will still not return anything to stdout . - aleksandr barakin
  • That is, you do not know how to fix the problem with subprocess.pipe? :) Running the shell is easy, I would like to understand what is the cause of my problem. - approximatenumber
  • one
    but it is possible that I misunderstood you, and your script is not waiting for anything from stdout , but just waiting for the completion of the running process. then, perhaps, the problem is that the convert ... label:@- ... process convert ... label:@- ... waits for the text of the label to appear in stdin , and nothing is passed to it in stdin . To verify, pass the inscription directly using the label command. - aleksandr barakin

1 answer 1

It was decided, as everyone expected, by calling Shells pipe ( ...Popen("%s | %s %s" ... ). Although this is a partial solution to the problem, but in the end I accept it as a solution.

 class Screenshot: file = '/tmp/screenshot.png' convert = 'convert -pointsize 20 -font Courier -fill black -background white label:@-' def make_shot(self, cmd): run_cmd = subprocess.Popen("%s | %s %s" % (cmd, self.convert, self.file), shell=True) return self.file def get_top(): top = Screenshot().make_shot('top -n1 -b') return top