Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to convert to string? #40

Closed
suhasghorp opened this issue Aug 9, 2022 · 7 comments
Closed

How to convert to string? #40

suhasghorp opened this issue Aug 9, 2022 · 7 comments

Comments

@suhasghorp
Copy link

suhasghorp commented Aug 9, 2022

Hello,
Thanks for the awesome library. One quick question - once i have the byte buffer after doing the encode(), how do I convert it to a string so that or "\x01" characters are converted to "^A" characters ? I tried various different ways to do this, like repr(byte_buffer) or (ord(x) in bye_buffer) etc. but could not.
My bytes array looks like below -
b'8=FIX.4.4\x019=65\x0135=0\x0152=20220809-21:37:06.893\x0149=TRADEWEB\x0156=ABFIXREPO\x01347=UTF-8\x0110=045\x01'
Any idea ? Thanks

@da4089
Copy link
Owner

da4089 commented Aug 9, 2022

I think that bytes array is actually correct.

b'\x01' is Python's way of describing a byte with an integer value of 1. '^A' is an alternative representation (not understood by Python) of the same thing: it represents the keystroke Control-A, which used to (and might even still do in some cases) generate a character with an integer value 1 at a terminal. This is also sometimes referred to as SOH -- again, a byte with an integer value of 1, but in this case that's the ASCII abbreviation for Start Of Header, which was what that byte meant in standard ASCII.

I don't think this is what you need, but if for some reason you actually need a string with the '^' and 'A' as two separate characters representing the field separator, you could use the replace() function (defined for both string and bytes types), like b'8=FIX.4.4\x019=65\x0135=0\x01'.replace(b'\x01', b'^A') and it will replace that for you. But, I think it's unlikely this is what you want.

If you just want to convert the bytes type (suitable for sending to a socket, for instance) to a string (suitable for writing to a log file or something), you can use the decode() function, available on bytes instances. It will produce a UTF8-format string by default, but will retain the "\x01" representation of the separator byte, because that's how Python shows it.

Hope this helps!

@suhasghorp
Copy link
Author

Thanks! You are correct, I just need to store the FIX message as a string to another file for an application to process which is expecting "^A" as the delimiter. If I use decode, it seems that I lose the "\x01" chars all together.
This is string I get after decode -

8=FIX.4.49=6535=052=20220809-23:09:56.19649=TRADEWEB56=ABFIXREPO347=UTF-810=047

Is this expected? Or the "\x01" chars are present in the string but are unprintable ?
Thanks again.

@da4089
Copy link
Owner

da4089 commented Aug 9, 2022

Yes, it really depends on where the result is being displayed: the SOH character doesn't have a standard representation, which is why some things show "^A", and Python uses "\x01", and others just show nothing.

It's pretty common in FIX logging, for instance, to replace them with the vertical bar character for exactly this reason.

In fact, built into simplefix is a function that might be useful: simplefix.pretty_print(). Pass it the bytes object, and it'll do the replacement for you. It defaults to a | char, but you can pass an alternative as the second parameter if you prefer something else.

Help on function pretty_print in module simplefix:

pretty_print(buf, sep='|')
    Pretty-print a raw FIX buffer.

    :param buf: Byte sequence containing raw message.
    :param sep: Separator character to use for output, default is '|'.
    :returns: Formatted byte array.

@suhasghorp
Copy link
Author

Thank you, this function resolves my issue.

byte_buffer = message.encode()
str_buffer = simplefix.pretty_print(byte_buffer, '|').decode('utf-8').replace('|','^A')
print(str_buffer)

This prints -
8=FIX.4.4^A9=65^A35=0^A52=20220810-12:39:49.280^A49=TRADEWEB^A56=ABFIXREPO^A347=UTF-8^A10=036^A

@da4089
Copy link
Owner

da4089 commented Aug 11, 2022

Great that you've got it working. I think you could make one further simplification:

str_buffer = simplefix.pretty_print(byte_buffer, '^A').decode('utf-8')
print(str_buffer)

Doesn't save much, but ... you can have pretty_print do the replace for you.

@suhasghorp
Copy link
Author

I tried that first but got the following error. It looks like the "sep" parameter is expecting a char and "^A" is considered two chars.

Traceback (most recent call last): File "test_fix.py", line 14, in <module> str_buffer = simplefix.pretty_print(byte_buffer, '^A').decode('utf-8') File "/pylocal/simplefix/__init__.py", line 43, in pretty_print cooked[i] = ord(sep) if value == 1 else value TypeError: ord() expected a character, but string of length 2 found

Thanks.

@da4089
Copy link
Owner

da4089 commented Aug 11, 2022

Ah ... that feels like a bug. I'm going to reopen this issue, and investigate further, but ... it seems like it'd be much more useful if it accepted a string (or bytes) there?

I think this is in fact the very first bit of code that subsequently became simplefix. I haven't looked at it for ages.

@da4089 da4089 reopened this Aug 11, 2022
@da4089 da4089 closed this as completed in 1de83d2 Aug 13, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants