function to write on stderr with python2 and python3 - python-3.x

I'm writing a program that ought to work with both python2 and python3.
For this, I would like to have a function to write to stderr that works with both python versions.
Ideal I think would be something like:
def writeStdErr(message):
if sys.version_info >= (3, 0):
print(message, end = "", file = sys.stderr)
else:
sys.stderr.write(message)
the problem with this that python2 is, that print isn't a function, so I get
print(message, end = "", file = sys.stderr)
^
SyntaxError: invalid syntax
I could get rid of this by just adding eval:
def writeStdErr(message):
if sys.version_info >= (3, 0):
eval('print(message, end = "", file = sys.stderr)')
else:
sys.stderr.write(message)
however, I dislike this solution; I think it's general a bad idea to use eval.
Does anyone knows something better/has a better solution?
EDIT:
For anyone having the same problem in future, the following things seem works:
def writeStdErr(message):
sys.stderr.write(message)
or
from __future__ import print_function
import sys
def writeStdErr(message):
print(message, file=sys.stderr)
Thanks to all answers

If you are using Python2.7, you can import the new behaviour:
from __future__ import print_function
That should be the first line of code (but could go after a shebang).
Another alternative compatible with earlier versions is to create it in an external module.
if sys.version_info >= (3, 0):
from print_sderr3 import writeStdErr
else:
from print_stderr2 import writeStdErr
where you have implemented each one accordingly.
That is to answer your question, BUT, you can just use sys.stderr.write for both. The only difference is that in Python 3 it seems to return the number of characters written. If you do it on interactive mode:
>>> sys.stderr.write('aaaa\n')
aaaa
5
You get an extra 5, but that is just the return value.
>>> a = sys.stderr.write('aaaa\n')
aaaa
>>> a
5

Related

How do i import an input value? [duplicate]

I'm working on a documentation (personal) for nested matplotlib (MPL) library, which differs from MPL own provided, by interested submodule packages. I'm writing Python script which I hope will automate document generation from future MPL releases.
I selected interested submodules/packages and want to list their main classes from which I'll generate list and process it with pydoc
Problem is that I can't find a way to instruct Python to load submodule from string. Here is example of what I tried:
import matplotlib.text as text
x = dir(text)
.
i = __import__('matplotlib.text')
y = dir(i)
.
j = __import__('matplotlib')
z = dir(j)
And here is 3 way comparison of above lists through pprint:
I don't understand what's loaded in y object - it's base matplotlib plus something else, but it lack information that I wanted and that is main classes from matplotlib.text package. It's top blue coloured part on screenshot (x list)
Please don't suggest Sphinx as different approach.
The __import__ function can be a bit hard to understand.
If you change
i = __import__('matplotlib.text')
to
i = __import__('matplotlib.text', fromlist=[''])
then i will refer to matplotlib.text.
In Python 3.1 or later, you can use importlib:
import importlib
i = importlib.import_module("matplotlib.text")
Some notes
If you're trying to import something from a sub-folder e.g. ./feature/email.py, the code will look like importlib.import_module("feature.email")
Before Python 3.3 you could not import anything if there was no __init__.py in the folder with file you were trying to import (see caveats before deciding if you want to keep the file for backward compatibility e.g. with pytest).
importlib.import_module is what you are looking for. It returns the imported module.
import importlib
# equiv. of your `import matplotlib.text as text`
text = importlib.import_module('matplotlib.text')
You can thereafter access anything in the module as text.myclass, text.myfunction, etc.
spent some time trying to import modules from a list, and this is the thread that got me most of the way there - but I didnt grasp the use of ___import____ -
so here's how to import a module from a string, and get the same behavior as just import. And try/except the error case, too. :)
pipmodules = ['pycurl', 'ansible', 'bad_module_no_beer']
for module in pipmodules:
try:
# because we want to import using a variable, do it this way
module_obj = __import__(module)
# create a global object containging our module
globals()[module] = module_obj
except ImportError:
sys.stderr.write("ERROR: missing python module: " + module + "\n")
sys.exit(1)
and yes, for python 2.7> you have other options - but for 2.6<, this works.
Apart from using the importlib one can also use exec method to import a module from a string variable.
Here I am showing an example of importing the combinations method from itertools package using the exec method:
MODULES = [
['itertools','combinations'],
]
for ITEM in MODULES:
import_str = "from {0} import {1}".format(ITEM[0],', '.join(str(i) for i in ITEM[1:]))
exec(import_str)
ar = list(combinations([1, 2, 3, 4], 2))
for elements in ar:
print(elements)
Output:
(1, 2)
(1, 3)
(1, 4)
(2, 3)
(2, 4)
(3, 4)
Module auto-install & import from list
Below script works fine with both submodules and pseudo submodules.
# PyPI imports
import pkg_resources, subprocess, sys
modules = {'lxml.etree', 'pandas', 'screeninfo'}
required = {m.split('.')[0] for m in modules}
installed = {pkg.key for pkg in pkg_resources.working_set}
missing = required - installed
if missing:
subprocess.check_call([sys.executable, '-m', 'pip', 'install', '--upgrade', 'pip'])
subprocess.check_call([sys.executable, '-m', 'pip', 'install', *missing])
for module in set.union(required, modules):
globals()[module] = __import__(module)
Tests:
print(pandas.__version__)
print(lxml.etree.LXML_VERSION)
I developed these 3 useful functions:
def loadModule(moduleName):
module = None
try:
import sys
del sys.modules[moduleName]
except BaseException as err:
pass
try:
import importlib
module = importlib.import_module(moduleName)
except BaseException as err:
serr = str(err)
print("Error to load the module '" + moduleName + "': " + serr)
return module
def reloadModule(moduleName):
module = loadModule(moduleName)
moduleName, modulePath = str(module).replace("' from '", "||").replace("<module '", '').replace("'>", '').split("||")
if (modulePath.endswith(".pyc")):
import os
os.remove(modulePath)
module = loadModule(moduleName)
return module
def getInstance(moduleName, param1, param2, param3):
module = reloadModule(moduleName)
instance = eval("module." + moduleName + "(param1, param2, param3)")
return instance
And everytime I want to reload a new instance I just have to call getInstance() like this:
myInstance = getInstance("MyModule", myParam1, myParam2, myParam3)
Finally I can call all the functions inside the new Instance:
myInstance.aFunction()
The only specificity here is to customize the params list (param1, param2, param3) of your instance.
You can also use exec built-in function that execute any string as a Python code.
In [1]: module = 'pandas'
...: function = 'DataFrame'
...: alias = 'DF'
In [2]: exec(f"from {module} import {function} as {alias}")
In [3]: DF
Out[3]: pandas.core.frame.DataFrame
For me this was the most readable way to solve my problem.

trying to print output using sys.stdout, but not able to print same as it coming none

I am trying to print output using sys.stdout but getting none on stdout. please check
# Read input from STDIN. Print output to STDOUT
import math
import os
import random
import re
import sys
def stdin(s):
if (len(s)>=2 and len(s)<=10000):
ev=[s[i] for i in range(len(s)) if i%2==0]
od=[s[i] for i in range(len(s)) if i%2!=0]
even=''.join(map(str,ev))
odd=''.join(map(str,od))
sys.stdout.write("{0} {1}".format(even,odd)) #print outpout using stdout but error got
sys.stdout.flush()
if __name__ == '__main__':
s = input().strip()
stdin(s)
By default python uses stdout when using the built in print() function. It will also read from stdin when using input(). I would suggest going that route as it will be less prone to error. Otherwise could you share the exact error message you are getting? The code is running without error for me.

Why no call_at_threadsafe and call_later_threadsafe?

I'm using Python 3.5.2 in Windows 32bits and aware that asyncio call_at is not threadsafe, hence following code won't print 'bomb' unless I uncomment the line loop._write_to_self().
import asyncio
import threading
def bomb(loop):
loop.call_later(1, print, 'bomb')
print('submitted')
# loop._write_to_self()
if __name__ == '__main__':
loop = asyncio.get_event_loop()
threading.Timer(2, bomb, args=(loop,)).start()
loop.run_forever()
However I couldn't find a piece of information about why call_at_threadsafe and call_later_threadsafe is implemented. Is the reason ever exists?
Simply use loop.call_soon_threadsafe to schedule loop.call_later:
loop.call_soon_threadsafe(loop.call_later, 1, print, 'bomb')

name unicode not defined python3

i have been trying to run this code
this is the error
File "C:/hari/Academics/python/py programs/gui qt4/book/calculator.py", line 27, in updateUi
text = unicode(self.lineedit.text(),'utf-8')
NameError: name 'unicode' is not defined
the code :
from __future__ import division
from math import *
from PyQt4.QtGui import *
from PyQt4.QtCore import *
import sys
class Form(QDialog):
def __init__(self,parent =None):
super(Form,self).__init__(parent)
self.browser =QTextBrowser()
self.lineedit =QLineEdit("type an exp")
self.lineedit.selectAll()
layout=QVBoxLayout()
layout.addWidget(self.browser)
layout.addWidget(self.lineedit)
self.setLayout(layout)
self.lineedit.setFocus()
self.connect(self.lineedit, SIGNAL("returnPressed()"), self.updateUi)
self.setWindowTitle("Calculate")
def updateUi(self):
try:
text = unicode(self.lineedit.text())
print(type(text))
self.browser.append(text+" = <b>"+eval(text)+"</b>" )
except:
self.browser.append("<font color=red>"+ text + " is invalid</font>")
app=QApplication(sys.argv)
f=Form()
f.show()
app.exec_()
in python 3 strings are unicode by default.
Remove the unicode function, replace by str.
https://docs.python.org/3.0/whatsnew/3.0.html#text-vs-data-instead-of-unicode-vs-8-bit
There's also a little recipe to make the code python 2 & 3 compatible:
try:
unicode # check if unicode is defined
except NameError: # not found: python 3: replace by str
unicode = str
Like Bakuriu said in his comment, never use a bare except:
Prefer:
except Exception as e:
print("Problem "+repr(e))
# the line below requires some HTML normalization or resulting
# html could be incorrect
import re
ne = re.sub("[^\w]"," ",str(e))
self.browser.append("<font color=red>"+ne+"</font>")
Now you have the real/next exception displayed.
Hope you are using Python 3 , so please replace
Unicode function with String Str function.
def updateUi(self):
try:
text = str(self.lineedit.text()) ##replaced here

Syntax error whenever i try to use sys.stderr

I've got a problem using the standard error, whenever I try to use it my computer gives me a syntax error which i can't explain.
So this is my code:
import sys
def main(argv):
if len(argv) != 3:
print("Usage: python walk.py n l", file=sys.stderr)
else:
l = argv[2]
n = argv[1]
print("You ended up", simuleer(n,l), "positions from the starting point.")
if __name__ == "__main__":
main(sys.argv)
And this is my error
MacBook-Air-van-Luuk:documents luuk$ python walk.py 5 1 2
File "walk.py", line 21
print("Usage: python walk.py n l", file=sys.stderr)
^
I hope someone can explain me why this happens, thanks in advance!
You think you're using Python 3.x, but it's actually Python 2.x. On most systems python executable means Python 2.x.
print is not a function in Python 2.x, and can't be used like that, causing a syntax error.
You should look for some way to run Python 3.x instead.
For this particular case, you could also use from __future__ import print_function, which would make the code compatible with both versions.
There is a way to fix it
Just remove the "file=" from print method
e.g:
print("Usage: python walk.py n l", sys.stderr)

Resources