diff --git a/src/Ophis/Errors.py b/src/Ophis/Errors.py
index 0711ca0..bdc9d65 100644
--- a/src/Ophis/Errors.py
+++ b/src/Ophis/Errors.py
@@ -7,6 +7,8 @@
 # You may use, modify, and distribute this file under the MIT
 # license: See README for details.
 
+import sys
+
 count = 0
 currentpoint = "<Top Level>"
 
@@ -15,10 +17,10 @@ def log(err):
 the global error count."""
     global count
     count = count+1
-    print currentpoint+": "+err
+    print>>sys.stderr, currentpoint+": "+err
 
 def report():
     "Print out the number of errors."
-    if count == 0: print "No errors"
-    elif count == 1: print "1 error"
-    else: print str(count)+" errors"
+    if count == 0: print>>sys.stderr, "No errors"
+    elif count == 1: print>>sys.stderr, "1 error"
+    else: print>>sys.stderr, str(count)+" errors"
diff --git a/src/Ophis/Frontend.py b/src/Ophis/Frontend.py
index 0c418a1..8d2a7c4 100644
--- a/src/Ophis/Frontend.py
+++ b/src/Ophis/Frontend.py
@@ -6,6 +6,7 @@ import Ophis.Errors as Err
 import Ophis.Opcodes as Ops
 import Ophis.IR as IR
 import Ophis.CmdLine as Cmd
+import sys
 import os
 
 # Copyright 2002-2012 Michael C. Martin and additional contributors.
@@ -309,11 +310,18 @@ def parse_line(ppt, lexemelist):
 def parse_file(ppt, filename):
     "Loads an Ophis source file, and returns an IR list."
     Err.currentpoint = ppt
-    if Cmd.verbose > 0: print "Loading "+filename
+    if Cmd.verbose > 0:
+        if filename != '-':
+            print>>sys.stderr, "Loading "+filename
+        else:
+            print>>sys.stderr, "Loading from standard input"
     try:
-        f = file(filename)
-        linelist = f.readlines()
-        f.close()
+        if filename != '-':
+            f = file(filename)
+            linelist = f.readlines()
+            f.close()
+        else:
+            linelist = sys.stdin.readlines()
         pptlist = ["%s:%d" % (filename, i+1) for i in range(len(linelist))]
         lexlist = map(lex, pptlist, linelist)
         IRlist = map(parse_line, pptlist, lexlist)
diff --git a/src/Ophis/Macro.py b/src/Ophis/Macro.py
index f4cdce9..ee3a68f 100644
--- a/src/Ophis/Macro.py
+++ b/src/Ophis/Macro.py
@@ -61,6 +61,6 @@ def dump():
     global macros
     for mac in macros:
         body = macros[mac]
-        print "Macro: "+mac
-        for node in body: print node
-        print ""
+        print>>sys.stderr, "Macro: "+mac
+        for node in body: print>>sys.stderr, node
+        print>>sys.stderr, ""
diff --git a/src/Ophis/Main.py b/src/Ophis/Main.py
index 0977e0a..6396c41 100644
--- a/src/Ophis/Main.py
+++ b/src/Ophis/Main.py
@@ -20,13 +20,13 @@ import Ophis.Opcodes
 
 def usage():
     "Prints a usage message and quits."
-    print "Usage:"
-    print "\tOphis [options] infile outfile"
-    print ""
-    print "Options:"
-    print "\t-6510 Allow 6510 undocumented opcodes"
-    print "\t-65c02 Enable 65c02 extensions"
-    print "\t-v n Set verbosity to n (0-4, 1=default)"
+    print>>sys.stderr, "Usage:"
+    print>>sys.stderr, "\tOphis [options] infile outfile"
+    print>>sys.stderr, ""
+    print>>sys.stderr, "Options:"
+    print>>sys.stderr, "\t-6510 Allow 6510 undocumented opcodes"
+    print>>sys.stderr, "\t-65c02 Enable 65c02 extensions"
+    print>>sys.stderr, "\t-v n Set verbosity to n (0-4, 1=default)"
     sys.exit(1)
 
 def run_all(infile, outfile):
@@ -55,10 +55,16 @@ def run_all(infile, outfile):
 
     if Err.count == 0:
         try:
-            output = file(outfile, 'wb')
+            if outfile == '-':
+                output = sys.stdout
+            else:
+                output = file(outfile, 'wb')
             output.write("".join(map(chr, a.output)))
+            output.flush()
+            if outfile != '-':
+                output.close()
         except IOError:
-            print "Could not write to "+outfile
+            print>>sys.stderr, "Could not write to "+outfile
     else:
         Err.report()
 
@@ -77,9 +83,9 @@ def run_ophis():
                 Ophis.CmdLine.verbose = int(x)
                 reading_arg = 0
             except ValueError:
-                print "FATAL: Non-integer passed as argument to -v"
+                print>>sys.stderr, "FATAL: Non-integer passed as argument to -v"
                 usage()
-        elif x[0] == '-':
+        elif x[0] == '-' and x != '-':
             if x == '-v':
                 reading_arg = 1
             elif x == '-6510':
@@ -87,22 +93,22 @@ def run_ophis():
             elif x == '-65c02':
                 chip_extension = Ophis.Opcodes.c02extensions
             else:
-                print "FATAL: Unknown option "+x
+                print>>sys.stderr, "FATAL: Unknown option "+x
                 usage()
         elif infile == None:
             infile = x
         elif outfile == None:
             outfile = x
         else:
-            print "FATAL: Too many files specified"
+            print>>sys.stderr, "FATAL: Too many files specified"
             usage()
 
     if infile is None:
-        print "FATAL: No files specified"
+        print>>sys.stderr, "FATAL: No files specified"
         usage()
 
     if outfile is None:
-        print "FATAL: No output file specified"
+        print>>sys.stderr, "FATAL: No output file specified"
         usage()
 
     Ophis.Frontend.pragma_modules.append(Ophis.CorePragmas)
diff --git a/src/Ophis/Passes.py b/src/Ophis/Passes.py
index 7b6fd25..8b20dd4 100644
--- a/src/Ophis/Passes.py
+++ b/src/Ophis/Passes.py
@@ -11,6 +11,7 @@
 # You may use, modify, and distribute this file under the MIT
 # license: See README for details.
 
+import sys
 import Ophis.Errors as Err
 import Ophis.IR as IR
 import Ophis.Opcodes as Ops
@@ -53,18 +54,18 @@ class Pass:
         """Prepares the environment and runs this pass, possibly 
         printing debugging information."""
         if Err.count == 0:
-            if Cmd.verbose > 1: print "Running: "+self.name
+            if Cmd.verbose > 1: print>>sys.stderr, "Running: "+self.name
             env.reset()
             self.prePass()
             node.accept(self, env)
             self.postPass()
             env.reset()
             if Cmd.verbose > 3:
-                print "Current labels:"
-                print env
+                print>>sys.stderr, "Current labels:"
+                print>>sys.stderr, env
             if Cmd.verbose > 2: 
-                print "Current IR:"
-                print node
+                print>>sys.stderr, "Current IR:"
+                print>>sys.stderr, node
 
 class FixPoint:
     """A specialized class that is not a pass but can be run like one.
@@ -82,7 +83,7 @@ class FixPoint:
                 p.go(node, env)
             if Err.count != 0: break
             if self.fixpoint(): break 
-            if Cmd.verbose > 1: print "Fixpoint failed, looping back"
+            if Cmd.verbose > 1: print>>sys.stderr, "Fixpoint failed, looping back"
         else:
             Err.log("Can't make %s converge!  Maybe there's a recursive dependency somewhere?" % self.name)
 
@@ -96,7 +97,7 @@ class DefineMacros(Pass):
         if self.inDef:
             Err.log("Unmatched .macro")
         elif Cmd.verbose > 2:
-            print "Macro definitions:"
+            print>>sys.stderr, "Macro definitions:"
             Macro.dump()
     def visitMacroBegin(self, node, env):
         if self.inDef:
@@ -392,7 +393,7 @@ class ExtendBranches(PCTracker):
                 node.data = ('jmp', expr)
                 node.nodetype = "Absolute"
                 if Cmd.verbose > 0:
-                    print str(node.ppt) + ": WARNING: bra out of range, replacing with jmp"
+                    print>>sys.stderr, str(node.ppt) + ": WARNING: bra out of range, replacing with jmp"
             else:
                 # Otherwise, we replace it with a 'macro' of sorts by hand:
                 # $branch LOC -> $reversed_branch ^+5; JMP LOC
@@ -403,7 +404,7 @@ class ExtendBranches(PCTracker):
                 node.nodetype='SEQUENCE'
                 node.data = expansion
                 if Cmd.verbose > 0:
-                    print str(node.ppt) + ": WARNING: "+opcode+" out of range, replacing with "+ExtendBranches.reversed[opcode] +"/jmp combo"
+                    print>>sys.stderr, str(node.ppt) + ": WARNING: "+opcode+" out of range, replacing with "+ExtendBranches.reversed[opcode] +"/jmp combo"
             self.expanded += 1
             node.accept(self, env)
         else:
@@ -435,7 +436,7 @@ class Assembler(Pass):
 
     def postPass(self):
         if Cmd.verbose > 0 and Err.count == 0:
-            print "Assembly complete: %s bytes output (%s code, %s data, %s filler)" \
+            print>>sys.stderr, "Assembly complete: %s bytes output (%s code, %s data, %s filler)" \
                 % (len(self.output), self.code, self.data, self.filler)
 
     def outputbyte(self, expr, env):