I've seen alot of people asking what language they should learn next, and I often question how well they know the languages they claim to. Since I know it is hard to just go and program, I have decided to ask some more advanced Python questions, and see who the first to answer correctly is....

(code follows questions)

1) What does the code do?
2) What flaw(s) do(es) it have? (and recode it fixing the problems)
3) What is a rough Windows alternative?
4) What advantages/disadvantages does the Windows version have? (The Win version I came up with had 1 minor advantage, 2 major disadvantages)
5) How could you implement it so both the Linux and Windows versions co-exist in the same file, with the proper version used depending on the platform (needs to be transparent to the programmer using it)?


Code:
import os, pty, threading

class MPlayer(threading.Thread):
   def __init__(self, args):
      threading.Thread.__init__(self)
      if (type(args) == str):
         args = (args,)
      self.mplayer_args = args
   
   def run(self):
      pid, fd = pty.fork()
      if (pid):
         self.mplayer_pid = pid
      else:
         os.execvp("mplayer", ("mplayer",) + self.mplayer_args)


(btw Kerm/admins, why aren't there boxes around code and quote anymore?)
There are; it has a white border. I moved the CSS into a separate file sheet (which made most pages 33%-50% of their previous size), and I changed a few things around. I can change it back if you want.

Ontopic, since I'm not a Python master yet, I can only guess that it reads off the args it was given, opens up a new thread, and then launches mplayer, passing its args, in that thread.
KermMartian wrote:
There are; it has a white border. I moved the CSS into a separate file sheet (which made most pages 33%-50% of their previous size), and I changed a few things around. I can change it back if you want.


some sort of border would be nice

Quote:
Ontopic, since I'm not a Python master yet, I can only guess that it reads off the args it was given, opens up a new thread, and then launches mplayer, passing its args, in that thread.


Good start for #1, but it does/can do several more things that are important....
I have only limited knowledge of Python, but my guess is that it takes a bunch of arguments that are filenames and plays them in the OS's default media player?
jpez wrote:
I have only limited knowledge of Python, but my guess is that it takes a bunch of arguments that are filenames and plays them in the OS's default media player?


No, Kerm had it right that it launches it in mplayer in a new thread ( mplayer's homepage: http://www.mplayerhq.hu/design7/news.html ), and the arguments don't necessarily need to be filenames (obviously it needs something to play, but it could also specify the cache, video output, audio output, etc...)
*bump*

Does no one know? I'm a bit disapointed, I figured surely SOMEONE would have got it by now....

If no one gets it in a couple more days I guess I'll just post the answer...
First time even looking at this thread/code.
(1) The class is a "child" that runs mplayer in the process.
(2) It uses a module that can only be found on Linux and Mac (Only a part-time Windows user would say that...). Further, it doesn't actually do anything with the PID once it has it. I don't actually know enough Python to say too much more.
(3) os.spawn???() will open mplayer in a new process, but I doubt they'll have the intended effect. The popen() family might work better.
(4) Can't answer this one.
(5) I recall a couple functions in either 'os' or 'sys' that will tell you what OS you are running. Then, you can use an if in run to do the appropriate code. One of the popen() functions might allow OS-independence, but I doubt it.
Here's a hint on what it is overcoming and what the windows version must do.

mplayer will hijack stdin, stdout, and stderr upon running

Answer #1 is mostly answered, so I will finish it off. Whatever spawns an MPlayer class instance can query whether or not mplayer has exited via isAlive(). The PID is recorded so that, if necessary, mplayer can be killed (such as on exit, overriding the default behavior to wait for child processes). Lastly, the fd can be used to record all output of mplayer

Answer #2 Upon creating an instance, mplayer will rapidly max out the pty's buffer. The solution (and need for the thread) is to simply record all output, as such: (this also allows isAlive to work correctly)


Code:
class MPlayer(threading.Thread):
   def __init__(self, args):
      threading.Thread.__init__(self)
      if (type(args) == str):
         args = (args,)
      self.mplayer_args = args
   
   def run(self):
      pid, fd = pty.fork()
      if (pid):
         self.mplayer_pid = pid
         term = os.fdopen(fd)
         self.mplayer_out = term.read()
      else:
         os.execvp("mplayer", ("mplayer",) + self.mplayer_args)


@proegssilb, you are on the right track with #3, but there is something the windows version of python can do that the linux/mac ones can't, and that is the key to getting a correctly working os.spawn....
Here's what I know about #3:

  • Windows has 'cheap threads' that share the same memory space as the parent process
  • Windows has a built-int IPC, I believe Linux doesn't (excluding pipes, DCOP doesn't really count)
  • The path-using versions of spawn() don't work on windows (OK, I looked that up yesterday)
  • popen3() gives you a tuple containing stdout, stderr, stdin (which version of popen looked up)
  • only Linux c--:CLICK:

#3: One rough windows alternative would be to use popen3() to execute the command the command (once converted to a string, including args).
#4 That version actually does work on *nix, but doesn't catch the return value without modification. Furthermore, it creates a child process, not a thread. To make matters worse, you can't kill the process, as you don't get its PID.
#5 I would use either an if statement with os.name (thanks for the hint in "Should I start learning Python", kllrnohj!) or popen3(), the latter being OS-independant.
Interesting idea using popen3(), BUT if I remember from when I was doing my tests, it doesn't "fool" mplayer, which gets the stdin, stdout, stderr straight from the terminal (or so it seems, it might not be using stdin, stdout, and stderr at all), hence the need to pty.fork() in the linux version. That is the real problem for the windows version. How to get something similar to pty.fork()?

os.spawn*() is the right place to be looking. Since windows doesn't keep programs in the path (not anything significant, anyway), it doesn't matter than none of the spawn*()s keep the path. Assume the path to mplayer is known, and defined in the python string variable MPLAYER_PATH

#5 is pretty easy, I'm surprised no one really banged it out yet (proegssilb got really close though, but it wasn't really complete). The key is that you can put class definitions inside conditionals.


Code:
if (os.name == "nt"):
   class MPlayer:
       #win32 stuff
       pass
elif (os.name == "posix"):
   class MPlayer:
       #*nix stuff
       pass
else:
    raise "No MPlayer class defined for os %s" % os.name
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 1
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement