I have a value out of I²C register which is 2 bytes wide like 01C5 (as string).
For my application, i have to swap high and low byte.
I tried it this way:
valueLow = hex(int(value,16) >> 8)
valueHigh = hex(int(value,16) & 0x0011)
but the results I get are now what they should look like.
Do you have a better solution?
Use this to get the byte-swapped value:
swappedValue = hex(value<<8&0xff00 | value>>8&0x00ff)
or, if value is a string,
swappedValue = hex(int(value,16)<<8&0xff00 |int(value,16)>>8&0x00ff)
If you need a number (for I2C), try:
swappedValue = int(value,16)<<8&0xff00 | int(value,16)>>8&0x00ff
Related
I want to print some data on a left justification (alignment) but the spacing might need to change in real-time before printing so I would like to use a variable instead of a fixed hard-coded space width.
I tried using a variable to hold the number of spaces but that does work:
string_alignment_spacing = 15
print("|{:<string_alignment_spacing }|{:<string_alignment_spacing }|{:<string_alignment_spacing }|".format('Butter', 'Toast', 'Gravy'))
I was hoping to get the following output:
|Butter |Toast |Gravy |
But instead get:
ValueError: Invalid format specifier
Put string_alignment_spacing inside {} and in the format() method set keyword argument string_alignment_spacing=string_alignment_spacing:
string_alignment_spacing = 15
print("|{:<{string_alignment_spacing}}|{:<{string_alignment_spacing}}|{:<{string_alignment_spacing}}|".format('Butter', 'Toast', 'Gravy', string_alignment_spacing=string_alignment_spacing))
Prints:
|Butter |Toast |Gravy |
EDIT (With f-strings):
string_alignment_spacing = 15
print(f'|{"Butter":<{string_alignment_spacing}}|{"Toast":<{string_alignment_spacing}}|{"Gravy":<{string_alignment_spacing}}|')
In the following code,string_alignment_spacing is only str and there's an illegal space behind it.
print("|{:<string_alignment_spacing }|{:<string_alignment_spacing }|{:<string_alignment_spacing }|".format('Butter', 'Toast', 'Gravy'))
Try the following code
formatstr = "|{:<%s}|{:<%s}|{:<%s}|"%(15,15,15)
print(formatstr.format('Butter', 'Toast', 'Gravy'))
So we can generate a unique id with str(uuid.uuid4()), which is 36 characters long.
Is there another method to generate a unique ID which is shorter in terms of characters?
EDIT:
If ID is usable as primary key then even better
Granularity should be better than 1ms
This code could be distributed, so we can't assume time independence.
If this is for use as a primary key field in db, consider just using auto-incrementing integer instead.
str(uuid.uuid4()) is 36 chars but it has four useless dashes (-) in it, and it's limited to 0-9 a-f.
Better uuid4 in 32 chars:
>>> uuid.uuid4().hex
'b327fc1b6a2343e48af311343fc3f5a8'
Or just b64 encode and slice some urandom bytes (up to you to guarantee uniqueness):
>>> base64.b64encode(os.urandom(32))[:8]
b'iR4hZqs9'
TLDR
Most of the times it's better to work with numbers internally and encode them to short IDs externally. So here's a function for Python3, PowerShell & VBA that will convert an int32 to an alphanumeric ID. Use it like this:
int32_to_id(225204568)
'F2AXP8'
For distributed code use ULIDs: https://github.com/mdipierro/ulid
They are much longer but unique across different machines.
How short are the IDs?
It will encode about half a billion IDs in 6 characters so it's as compact as possible while still using only non-ambiguous digits and letters.
How can I get even shorter IDs?
If you want even more compact IDs/codes/Serial Numbers, you can easily expand the character set by just changing the chars="..." definition. For example if you allow all lower and upper case letters you can have 56 billion IDs within the same 6 characters. Adding a few symbols (like ~!##$%^&*()_+-=) gives you 208 billion IDs.
So why didn't you go for the shortest possible IDs?
The character set I'm using in my code has an advantage: It generates IDs that are easy to copy-paste (no symbols so double clicking selects the whole ID), easy to read without mistakes (no look-alike characters like 2 and Z) and rather easy to communicate verbally (only upper case letters). Sticking to numeric digits only is your best option for verbal communication but they are not compact.
I'm convinced: show me the code
Python 3
def int32_to_id(n):
if n==0: return "0"
chars="0123456789ACEFHJKLMNPRTUVWXY"
length=len(chars)
result=""
remain=n
while remain>0:
pos = remain % length
remain = remain // length
result = chars[pos] + result
return result
PowerShell
function int32_to_id($n){
$chars="0123456789ACEFHJKLMNPRTUVWXY"
$length=$chars.length
$result=""; $remain=[int]$n
do {
$pos = $remain % $length
$remain = [int][Math]::Floor($remain / $length)
$result = $chars[$pos] + $result
} while ($remain -gt 0)
$result
}
VBA
Function int32_to_id(n)
Dim chars$, length, result$, remain, pos
If n = 0 Then int32_to_id = "0": Exit Function
chars$ = "0123456789ACEFHJKLMNPRTUVWXY"
length = Len(chars$)
result$ = ""
remain = n
Do While (remain > 0)
pos = remain Mod length
remain = Int(remain / length)
result$ = Mid(chars$, pos + 1, 1) + result$
Loop
int32_to_id = result
End Function
Function id_to_int32(id$)
Dim chars$, length, result, remain, pos, value, power
chars$ = "0123456789ACEFHJKLMNPRTUVWXY"
length = Len(chars$)
result = 0
power = 1
For pos = Len(id$) To 1 Step -1
result = result + (InStr(chars$, Mid(id$, pos, 1)) - 1) * power
power = power * length
Next
id_to_int32 = result
End Function
Public Sub test_id_to_int32()
Dim i
For i = 0 To 28 ^ 3
If id_to_int32(int32_to_id(i)) <> i Then Debug.Print "Error, i=", i, "int32_to_id(i)", int32_to_id(i), "id_to_int32('" & int32_to_id(i) & "')", id_to_int32(int32_to_id(i))
Next
Debug.Print "Done testing"
End Sub
Yes. Just use the current UTC millis. This number never repeats.
const uniqueID = new Date().getTime();
EDIT
If you have the rather seldom requirement to produce more than one ID within the same millisecond, this method is of no use as this number‘s granularity is 1ms.
I want to retrieve hexadecimal data from user, using python. How to retrieve the data from user and convert it to hex.
#to read varibales from Python
STX = '\xF7' #hex(input("enter STX Value"))
Deviceid = hex(input("enter device id"))
subid = hex(input("enter address of the Device and load details"))
Comnd = hex(41)
Data = hex(01)
EorCode = input("enter EOR Code")
ADD_sum = '\xF2' #hex(input("Enter Add sum value"))
tuple = (STX, Deviceid,subid,Comnd,Data,EorCode,ADD_sum)
print tuple
i am reading the above data from user,but i am getting output as follows
enter device id03
enter address of the Device and load details81
enter EOR Code32
('\xf7', '0x3', '0x51', '0x29', '0x1', '0x20', '\xf2')
But i need to be printed as 0x03 and 0x01.
I am very new to PYTHON please help.
You're looking for string formatting:
>>> "0x{0:04x}".format(42)
'0x002a'
So you'll want to modify your lines like so:
Deviceid = "0x{0:2x}".format((input("enter device id"))
Also, if any other Python developer will be looking at this code you may want to look at the Python style guide, PEP8.
Following the style guide, your code might look like this:
stx = '\xF7' # hex(input("enter STX Value"))
device_id = hex(input("enter device id")) # deviceid might also be fine
sub_id = hex(input("enter address of the Device and load details"))
comnd = hex(41)
data = hex(01)
eor_code = input("enter EOR Code")
add_sum = '\xF2' # hex(input("Enter Add sum value"))
values = (stx, device_id, sub_id, comnd, data, eor_code, add_sum)
print values # tuple is a keyword - it's best to *not* override them if possible
Of course,
A style guide is about consistency. Consistency with this style guide is important. Consistency within a project is more important. Consistency within one module or function is most important.
But most importantly: know when to be inconsistent -- sometimes the style guide just doesn't apply. When in doubt, use your best judgment. Look at other examples and decide what looks best. And don't hesitate to ask!
It seems to me that all you really need is to specify how to print the numbers, but hex function returns a string.
Because in python, '10' is a string and this is different from 10, which is an int. Python is dynamicaly, but strongly typed language.
So in order to have output you want, you may choose from 2 options:
write your own function to convert numbers to hexaxecimal numbers in a format you want and use it instead of hex:
def myhex(num):
return '0x%02x' % num
this 0x%02x means - first, 0x is just normal text which you probably want to prefix all your hexadecimal numbers, %02x means: print argument as hexadecimal number of length 2, prefixed with 0 if it's too short (one-digit hexadecimal number).
do not convert numbers to hex when reading values (it's probably a good thing to work with numbers represented as numbers) and print them formated to your specification at the end:
print '(' + ', '.join('%0x02x' % x for x in tuple) + ')'
which creates list of all values in tuple (btw, avoid using keywords as your variable names when possible) converted to correct 2-digit hexadecimal numbers with 0x prefixes, joins them using ', ' and surrounds them with parentheses. But feel free to change it - I'm just building on your example and trying to duplicate your output.
I have this set of constants declarations
self.POUTPUT = 1
self.PPWM = 2
self.PINPUT = 4
self.PUNUSED = 8
self.PSONAR = 16
self.PULTRA = 32
self.PSERVOD = 64
self.PSTEPPER = 128
self.PCOUNT = 256
self.PINPUTDOWN = 512
self.PINPUTNONE = 1024
What is the pythonic way of checking whether a value matches any of the input states (4,512 and 1024) please?
Extra info: I'd normally just use bit pattern checking in simpler languages but I wondered if there was a better way in Python :)
Basically it is that each pin can have one of the I/O states above but if a pin is any of of the input values then one action occurs
e.g if pin == 4 or 512 or 1024 -> do something
if SOME_DATA & self.PINPUTNONE: # do somethign
is how people usually do it
to check alot
ANY = self.POUTPUT | self.PPWM | self.PINPUT | self.PUNUSED | self.PSONAR ...
if some_data & ANY: #do something
Testing for set membership (which is what you seem to be doing) is best done using a set.
self.input_states = {self.PINPUT, self.PINPUTDOWN, self.PINPUTNONE}
# later
if value in self.input_states:
do_something()
Of course you could handle this in a variety of essentially-identical ways, but one way or another you have to encode some knowledge as to which of these magic numbers are "input states".
Now if, as has been suggested, what you actually want is to do some bit-masking or tests based on whether a particular bit is set, then you want to take a look at the Python bitwise operators. In particular, to see if a value is equal to one of the ones you've got there, you'd use the bitwise and, which is denoted by & in Python. Joran's answer covers this use well, but the basic idea is:
if value & self.PINPUT: # Value has a 1 in the PINPUT bit (bit 3)
do_something()
Or if all of those input values trigger the same action:
if any(value & p for p in (self.PINPUT, self.PINPUTDOWN, self.PINPUTNONE)):
do_something()
When running psutil.virtual_memory() i'm getting output like this:
>>psutil.virtual_memory()
vmem(total=8374149120L, available=1247768576L)
But what unit of measurement are these values? The documentation simply claims that its the "total physical memory available" but nothing more. I'm trying to translate it into values that the user can actually relate to (ie GBs).
Thanks in advance
why not use bit shift operator:
if you want to display in human readable way, just like this!
values = psutil.virtual_memory()
display in MB format
total = values.total >> 20
display in GB format
total = values.total >> 30
1024^3 = Byte to Gigabyte
So I think this work:
import psutil
memory = psutil.virtual_memory().total / (1024.0 ** 3)
print(memory)
The unit of measurement specified is bytes . You can use this code to convert it into Gb's
When u use the value it will have a trailing "L" , but that doesn't affect the calculations.
values=psutil.virtual_memory()
def get_human_readable_size(self,num):
exp_str = [ (0, 'B'), (10, 'KB'),(20, 'MB'),(30, 'GB'),(40, 'TB'), (50, 'PB'),]
i = 0
while i+1 < len(exp_str) and num >= (2 ** exp_str[i+1][0]):
i += 1
rounded_val = round(float(num) / 2 ** exp_str[i][0], 2)
return '%s %s' % (int(rounded_val), exp_str[i][1])
total_size = get_human_readable_size(values.total)
It is in Bytes. To convert to a more readable format, simply use bytes2human
import psutil
from psutil._common import bytes2human
mem_usage = psutil.virtual_memory()
total_in_human_format = bytes2human(mem_usage[0])
print(total_in_human_format)
Output:
15.6G
Cant comment so I'm using "answer".
regarding "1024^3 = Byte to Gigabyte"
This is incorrect. The prefix Giga means 10^9. Therefore, a Gigabyte is 1000^3 Bytes. You can forget the extra 24.
Therefore: 1000^3 = Byte to Gigabyte
If you don't mind a 3rd party dependency, and you want to avoid magic numbers in your code, try pint.
This lets you work with units symbolically, and you can convert to whatever you want and get the "magnitude" at the end of your computation.
I like this because the code "self-documents" that the info from psutil is in bytes and then self-documents that we are converting to gigabytes.
import psutil
import pint
reg = pint.UnitRegistry()
vmem_info = psutil.virtual_memory()
total_gb = (vmem_info.total * reg.byte).to(reg.gigabyte).m
avail_gb = (vmem_info.available * reg.byte).to(reg.gigabyte).m
print('total_gb = {!r}'.format(total_gb))
print('avail_gb = {!r}'.format(avail_gb))