I'm trying to write some code to put data into a pipe, and I'd like the solution to be python 2.6+ and 3.x compatible.
Example:
from __future__ import print_function
import subprocess
import sys
if(sys.version_info > (3,0)):
print ("using python3")
def raw_input(*prmpt):
"""in python3, input behaves like raw_input in python2"""
return input(*prmpt)
class pipe(object):
def __init__(self,openstr):
self.gnuProcess=subprocess.Popen(openstr.split(),
stdin=subprocess.PIPE)
def putInPipe(self,mystr):
print(mystr, file=self.gnuProcess.stdin)
if(__name__=="__main__"):
print("This simple program just echoes what you say (control-d to exit)")
p=pipe("cat -")
while(True):
try:
inpt=raw_input()
except EOFError:
break
print('putting in pipe:%s'%inpt)
p.putInPipe(inpt)
The above code works on python 2.6 but fails in python 3.2 (Note that the above code was mostly generated with 2to3 -- I just messed with it a little to make it python 2.6 compatible.)
Traceback (most recent call last):
File "test.py", line 30, in <module>
p.putInPipe(inpt)
File "test.py", line 18, in putInPipe
print(mystr, file=self.gnuProcess.stdin)
TypeError: 'str' does not support the buffer interface
I've tried the bytes function (e.g. print(bytes(mystr,'ascii')) suggested here,
TypeError: 'str' does not support the buffer interface
But that doesn't seem to work.
Any suggestions?
The print function converts its arguments to a string representation, and outputs this string representation to the given file. The string representation always is of type str for both, Python 2.x and Python 3.x. In Python 3.x, a pipe only accepts bytes or buffer objects, so this won't work. (Even if you pass a bytes object to print, it will be converted to a str.)
A solution is to use the write() method instead (and flushing after writing):
self.gnuProcess.stdin.write(bytes(mystr + "\n", "ascii"))
self.gnuProcess.stdin.flush()
but python2 will complain about
bytes("something", "ascii")
if you use the mutable bytearray it will work in both python2 and python3 unaltered
self.gnuProcess.stdin.write(bytearray(mystr + "\n", "ascii"))
self.gnuProcess.stdin.flush()
Related
I know this may seem weird, but I'm trying to understand why the following happens:
I'm editing a Python program at work and when I run the following Python function:
def execute_shell_cmd(cmd):
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
for c in iter(lambda: process.stdout.read(1), b''):
print("type_c = ", type(c))
sys.stdout.write(c)
for e in iter(lambda: process.stderr.read(1), b''):
sys.stdout.write(e)
execute_shell_cmd("ls -l")
I get in the output that type_c is "bytes" and sys.stdout.write(c) runs regularly and prints one byte at a time.
But when I run this function from a standalone program, I get the following error:
TypeError: write() argument must be str, not bytes
How is that possible?
In Python 3, sys.stdout is always str-typed, with an encoding chosen by the PYTHONIOENCODING environment variable (and/or PYTHONUTF8 on Windows).
sys.stdout.buffer (i.e. a TextIOBase::buffer) is the underlying bytestream for the text-encoded stdout stream.
Since you're reading bytes from the subprocess, you'll need to also write to the byte-typed stream.
for c in iter(lambda: process.stdout.read(1), b''):
sys.stdout.buffer.write(c)
If, on the other hand, you do expect to be working with text, you may wish to configure the subprocess object to decode output to strings.
First, let me disclaim that I am extremely new to the coding world and work requires me to use Python going forward. My experience is limited to having just completed SANS 573.
I'm trying to obtain the Date and Time from image files in their various formats. Excuse the example, I'm just using this to try and get it working.
This what I currently have:
from pathlib import Path
from PIL import Image
L88 = Path("L88.jpg")
def corvette(L88):
imgobj=Image.open(L88)
info=imgobj._getexif()
return info[36867]
>>> corvette(L88)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in corvette
KeyError: 36867
>>>
I am running the function from the desktop which is where I have the image currently saved.
I don't understand the error messages.
KeyError: 36867 also has me confused too as when I looked up the tag, that is what I found and what worked when I just did my course.
The _getexif() method returns a Python datastructury called a dictionary.
The values in a dictionary are accessed by their key.
In this case, the keys are numbers.
Not all keys are mandatory. You can use the keys() method to see which ones exist. Try:
print(info.keys())
to see which keys exist.
You can also test if a key exists:
if 36867 in info:
return info[36867]
else:
return None
Note that there is a mapping between these numbers and their exif tags names available.
You can use that to create a readable dictionary.
Note that not all JPEG images have EXIF information. In that case, the _getexif() method returns None, so you should take that into account and test for that:
from PIL import Image, ExifTags
def image_info(path):
imgobj = Image.open(path)
info = imgobj._getexif()
if info is None:
return None
rv = {
ExifTags.TAGS[key]: info[key]
for key in info.keys()
}
return rv
Have error with xgoogle library
When I tried to use this code:
from xgoogle.search import GoogleSearch, SearchError
try:
gs = GoogleSearch("quick")
gs.results_per_page = 50
results = gs.get_results()
for res in results:
print (res.title.encode("utf8"))
print (res.desc.encode("utf8"))
print (res.url.encode("utf8"))
I get this error:
Traceback (most recent call last):
File "C:/Users/s.sorokin/PycharmProjects/hh.ru/xgoogle.py", line 1, in <module>
from xgoogle.search import GoogleSearch, SearchError
File "C:\Users\s.sorokin\PycharmProjects\hh.ru\xgoogle\search.py", line 124
raise SearchError, "Wrong parameter to first_indexed_in_previous: %s" % (str(interval))
^
SyntaxError: invalid syntax
As mentioned on the library's website, xgoogle was only built as a "quick hack". From what you mention, it looks like it's written in Python 2. You therefore will not be able to run it in Python 3, unless you rewrite it.
If you want to use Python 3, you'll likely have to find a library that supports it.
Not very new to programming or to python but incredibly green to using pyunit. Need to use it for my new job and I keep getting this error but only sometimes when it is run. My code below.
import unittest
from nose_parameterized import parameterized
from CheckFromFile import listFileCheck, RepresentsFloat
testParams = listFileCheck()
class TestSequence(unittest.TestCase):
#parameterized.expand(testParams)
def test_sequence(self, name, a, b):
if RepresentsFloat(a):
self.assertAlmostEqual(a,b,2)
else:
self.assertEqual(a,b)
if __name__ == '__main__':
unittest.main()
What is happening here is that my test case is pulling a method listFileCheck from another class. What it does is it reads values from the serial port communicating with the control board and compares them with a calibration file. It puts the control board values in an MD array along with the calibration file values. These values can be either str, int, or float.
I used the test case to compare the values to one another however I keep getting this error but only sometimes. After every 3rd or so run it fails with this error.
Error
Traceback (most recent call last):
File "C:\Python34\lib\unittest\case.py", line 57, in testPartExecutor
yield
File "C:\Python34\lib\unittest\case.py", line 574, in run
testMethod()
TypeError: 'NoneType' object is not callable
Process finished with exit code 0
Anyone know why I might be getting this error on occasion?
In Python 3 I imported the pySerial library so I could communicate with my Arduino Uno by serial commands.
It worked very well in Python 2.7 but in Python 3 I keep running into a error it says this
TypeError: unicode strings are not supported, please encode to bytes: 'allon'
In Python 2.7 the only thing I did differently is use raw_input but I don't know what is happening in Python 3. Here is my code
import serial, time
import tkinter
import os
def serialcmdw():
os.system('clear')
serialcmd = input("serial command: ")
ser.write (serialcmd)
serialcmdw()
ser = serial.Serial()
os.system('clear')
ser.port = "/dev/cu.usbmodem4321"
ser.baudrate = 9600
ser.open()
time.sleep(1)
serialcmdw()
Encode your data which you are writing to serial,in your case "serialcmd" to bytes.try the following :
ser.write(serialcmd.encode())
i found same you problem for learn "Arduino Python Serial" You can do another way this:
ser.write(str.encode('allon'))
If we have the string itself and not in a variable, we can do like this:
ser.write(b'\x0101')
This will convert the string to bytes type