A set object has no attribute 'encode' in socket module - python

I've tried to encode a set object and it failed to do it, claiming an AttributeError code.
Is there a way for it to work?
NOTE: I've been using the socket module.
albums = set()
for key, val in data.items():
albums.add(val['album'])
msg = albums.encode()

Are you trying to send some form of representation of albums via a socket? Then you need a binary representation of that object first. Using .encode() suggests that you want the string-representation of albumns, which you can get using msg = repr(albums).encode().

There are a few options here, but probably the easiest is to encode your dictionary using the Python pickle protocol.
To do that, use sending code like this:
import pickle
data_to_send = pickle.dumps(albums)
mysocket.send(data_to_send)
and receiving code like this:
import pickle
albums = pickle.loads(data_received_from_socket)
However, I want to warn you: using the socket module at all is a can of worms. It is low level and meant for experienced programmers. Compared to the question you've just asked, the other problems you'll have to deal with are probably a lot harder. For example, you have to think about how to delimit your messages before you figure out what to pass as the second parameter to socket.recv (the bufsize parameter).
I suggest you try something higher-level like Python's xmlrpc modules.

Related

Reading Binary data type from Redis published by Streambase(Java)

Here is the java code that, that publishes data to Redis
import com.streambase.sb.util.ByteOrderedDataOutput;
byte[] valuebuffer=null;
ByteOrderedDataOutput boutput = new ByteOrderedDataOutput(0,tuple.getByteOrder());
tuple.serialize(boutput,0);
valuebuffer = boutput.getBuffer();
byte[] keybuffer = null;
String keyvalue = redisStream+"."+keyFieldStr;
keybuffer = keyvalue.getBytes();
strLuaCommands += "redis.call('set',KEYS["+ (++keyCount) +"],ARGV["+ (++argCount) +"])";
keys.add(keybuffer);
args.add(valuebuffer);
I was able to get the data through python struct, but this is not in correct format.
import redis, struct
redis_client = redis.StrictRedis(host="abc.com", port=6379, db=0)
temp = redis_client.get('samplekey')
struct.unpack("<" + ("s" * (len(temp))), temp)
Tuple.serialize() uses the com.streambase.sb.util.ByteOrderedDataOutput class, which has never been part of the StreamBase public API. Therefore the Tuple.serialize() methods shouldn't be considered part of the public API, either.
Also, there's no particular reason to believe that the Python struct.unpack() method knows how to understand StreamBase's ByteOrderedDataOutput, whatever that is. So it's not surprising that what you are unpacking is not what you want.
One sort of quick-to-imagine workaround would be to use the StreamBase Python Operator to convert your StreamBase tuple into Python objects, and then use a Python script to write whatever you want to write into redis. Then, since you will have now encoded the stuff and decoded the stuff with the same Python complementary library functions, you'll have a much better chance of not mangling your data.

Setting value of a iterable property of a Python COM object

I am using pywin32 to automate some tasks in software that has an Automation Server technology interface (formerly OLE Automation Server).
This software comes with a somewhat detailed manual with code examples in VBA, C++ or Matlab but no Python. I have built a Python library that can do most of the functionalities built into the software but there are some parts I cannot do in Python.
I cannot change the value of a property if this property is contained in a iterable COM object.
What I can do:
[Documentation for Visibility property]
import win32com.client
app = win32com.client.Dispatch('NAME_OF_APP')
app.Visibility = True
As an example, with this code, I can change the visibility parameter of the software: if it runs with or without GUI.
What I cannot do:
[Documentation for getting and setting current device]
import win32com.client
app = win32com.client.Dispatch('NAME_OF_APP')
app.CurrentDevice(0) = 'NAME OF DEVICE'
I then get the following error:
SyntaxError: cannot assign to function call here. Maybe you meant '==' instead of '='?
This error makes sense to me but I cannot find a way to set any of these software properties when they come in the form of an iterable object. As soon as I have to specify an index, I don't know how to set the value.
From what I understand, in C++ we are able to change the value because of pointers but how can we achieve the same thing in Python? Is it possible or do I have to use some C++ code in parallel to my Python to run my library? I don't know anything in C++ so if I could avoid doing that, it would be good.
What I have tried
Of course, the 1st thing I tried was to change () to [] or {} which logically didn't work.
Then I used the Evaluate function in PyCharms to see what was hiding behind my app.CurrentDevice. I was hoping to find sub-attributes that I could then set but I don't see anything inside the object:
[Result of Evaluate on the CurrentDevice object]
Finally, I have tried the following:
import win32com.client
app = win32com.client.Dispatch('NAME_OF_APP')
curr_device = app.CurrentDevice(0)
curr_device = 'NAME OF DEVICE'
I wanted to affect the object to a variable and then change the value but of course, this only rewrites the variable curr-device with 'NAME OF DEVICE' but loses any link to COM Object.
I feel like my questions are similar to the following unanswered question:
How can I set the value of an indexed property of a COM object in Python?
It looks as if win32com is struggling to set the property if there is an additional argument to the put function, which is a little surprising.
First thing to do is to use
app = win32com.client.gencache.EnsureDispatch('NAME_OF_APP')
This creates a Python wrapper for the COM object (rather than just firing function calls at the object and hoping). This may in itself clear up your issue.
If not, here is a quite ugly way of working around. As you have identified, the relevant part of the type library is:
[id(0x00000018),propput, helpstring("property CurrentDevice")]
HRESULT CurrentDevice([in] long lAcq, [in] VARIANT pVal);
And you can use this to set the property at a low level.
win32com dispatch objects are a wrapper for the PyIDispatch object. All dispatch objects support the Invoke method, and you can use this to call the function yourself. NB. Since I don't have access to your COM object, I can't test, so this answer may need some tweaking (!).
The PyIDispatch documentation
Try:
import win32com.client as wc
import pythoncom
app = wc.gencache.EnsureDispatch('NAME OF APP')
app.Visibility=TRUE
newVal = wc.VARIANT(pythoncom.VT_VARIANT,'NAME OF DEVICE')
app._oleobj_.Invoke(24,0,pythoncom.INVOKE_PROPERTYPUT,0,0,newVal)
There are a lot of 'magic' numbers here, but basically:
24 = 0x00000018 in decimal: this is the Id of the property
0 = the LCID, the Locale Id ... I always set it to 0
pythoncom.INVOKE_PROPERTYPUT = the type of call.
0 = whether you care about the return type (you probably don't = False)
0 = first parameter, lAcq, as in CurrentDevice(0)
newVal = second paramter,pVal, the new device name as a VARIANT
I haven't tried this, but pythoncom is pretty good about converting VARIANT types, so you might not need the VARIANT creation, and can just use NAME OF DEVICE directly as the parameter.

Regarding Killing the switch in Python

I'm processing data from a serial port in python. The first byte indicates the start of a message and then the second byte indicates what type of message it is. Depending on that second byte we read in the message differently (to account for different types of messages, some are only data others are string and so on).
I now had the following structure. I have a general Message class that contains basic functions for every type of message and then derived classes that represent the different types of Messages (for example DataMessage or StringMessage). These have there own specific read and print function.
In my read_value_from_serial I read in all the byte. Right now I use the following code (which is bad) to determine if a message will be a DataMessage or a StringMessage (there are around 6 different type of messages but I simplify a bit).
msg_type = serial_port.read(size=1).encode("hex").upper()
msg_string = StringMessage()
msg_data = StringData()
processread = {"01" : msg_string.read, "02" : msg_data.read}
result = processread[msg_type]()
Now I want to simplify/improve this type of code. I've read about killing the switch but I don't like it that I have to create objects that I won't use in the end. Any suggestions for improving this specific problem?
Thanks
This is very close to what you have and I see nothing wrong with it.
class Message(object):
def print(self):
pass
class StringMessage(Message):
def __init__(self, port):
self.message = 'get a string from port'
def MessageFactory(port):
readers = {'01': StringMessage, … }
msg_type = serial_port.read(size=1).encode("hex").upper()
return readers[msg_type](port)
You say "I don't like it that I have to create objects that I won't use in the end". How is it that you aren't using the objects? If I have a StringMessage msg, then
msg.print()
is using an object exactly how it is supposed to be used. Did it bother you that your one instance of msg_string only existed to call msg_string.read()? My example code makes a new Message instance for every message read; that's what objects are for. That's actually how Object Oriented Programming works.

How to examine a urllib2 object in Python?

I am learning Python at the moment, and I come from a Java/C++ and C background. I usually like to "examine" the "objects" in debuggers to get a better understanding of what is going on, so excuse my question if it seems odd for python.
I was reading the urllib2 documentation at Python's website. The following example was shown:
>>> import urllib2
>>> for line in urllib2.urlopen('http://tycho.usno.navy.mil/cgi-bin/timer.pl'):
... if 'EST' in line or 'EDT' in line: # look for Eastern Time
... print line
I understand that urlopen will download the content of a page.
Does urlopen download the HTML content? I tried doing the following:
content = urllib2.urlopen('http://tycho.usno.navy.mil/cgi-bin/timer.pl')
print content
which yields an object. What is the nature of this object? Is it a dictionary-like object? If so, how can I examine what its key-values are? Would that be done using pickling in Python?
I am aware of the geturl() method, but I'd like to understand fully what urlopen() does and return.
Thank you!
import pdb
pdb.set_trace()
place this at any point in your source, like a breakpoint - it allows you to interactively inspect names and objects. once you're in, you can also use
import inspect
which has a number of options for inspecting the properties and methods of an object http://docs.python.org/library/inspect.html#module-inspect
also dir(my_object) is a cheap way to do something similar
From the documentation:
This function returns a file-like object with two additional methods: ...
So you can read it like a file (as you already do).
Yes, and you can print the content using:
print content.read()
also, I'd like to suggest IPython, so you can inspect object methods and attributes very easily:
dir(content)

shelve gives strange error

I'm trying to put some sites i crawled into a shelve, but the shelve won't accept any Site-objects. It will accept lists, strings, tuples, what have you, but as soon as i put in a Site-object, it crashes when i try to get the contents of the shelve
So when i fill up my shelve like this:
def add_to_shelve(self, site):
db = shelve.open("database")
print site, site.url
for word in site.content:
db[word] = site.url #site.url is a string, word has to be one too
shelve.open("database")['whatever'] works perfectly.
But if I do this:
def add_to_shelve(self, site):
db = shelve.open("database")
print site, site.url
for word in site.content:
db[word] = site #site is now an object of Site
shelve.open("database")['whatever'] errors out with this error message:
AttributeError: 'module' object has no attribute 'Site'
I'm completely stumped, and the pythondocs, strangely, don't have much info either. All they say is that the key in a shelve has to be a string, but the value or data can be "an arbitrary object"
It looks like you refactored your code after saving objects in the shelve. When retrieving objects from the shelve, Python rebuilds the object, and it needs to find the original class that, presumably, you have moved. This problem is typical when working with pickle (as the shelve module does).
The solution, as pduel suggests, is to provide a backwards-compatibility reference to the class in the same location that it used to be, so that pickle can find it. If you re-save all the objects, thereby rebuilding the pickles, you can remove that backwards-comatibility referece.
It seems that Python is looking for a constructor for a 'Site' object, and not finding it. I have not used shelve, but I recall the rules for what can be pickled are byzantine, and suspect the shelve rules are similar.
Try adding the line:
Site = sitemodule.Site
(with the name of the module providing 'Site') before you try unshelving. This ensures that a Site class can be found.

Categories

Resources