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

TypeError: must be str, not bytes #7

Closed
freephile opened this issue Jan 24, 2024 · 6 comments
Closed

TypeError: must be str, not bytes #7

freephile opened this issue Jan 24, 2024 · 6 comments
Assignees
Labels
bug Something isn't working python Python programming
Milestone

Comments

@freephile
Copy link
Owner

meza --version

Traceback (most recent call last):
  File "/usr/bin/meza", line 1269, in <module>
    main(sys.argv[1:])
  File "/usr/bin/meza", line 64, in main
    print( "Meza " + version.strip() )
TypeError: must be str, not bytes

in the code for meza.py

version = subprocess.check_output( ["git", "--git-dir={}/meza/.git".format(install_dir), "describe", "--tags" ] )
commit = subprocess.check_output( ["git", "--git-dir={}/meza/.git".format(install_dir), "rev-parse", "HEAD" ] )
print( "Meza " + format(version.strip()) )
print( "Commit " + format(commit.strip()) )

The version and commit are byte objects. We must use the format method to convert them to string before we can concatenate them to the string values (e.g. 'Meza ')

@freephile freephile added bug Something isn't working python Python programming labels Jan 24, 2024
@freephile freephile added this to the Release 1.39 milestone Jan 24, 2024
@freephile
Copy link
Owner Author

freephile commented Jan 24, 2024

Initially, I would get the error. After using format, I receive the proper version output (almost):

python3.11 meza/src/scripts/meza.py --version
Traceback (most recent call last):
  File "/opt/meza/src/scripts/meza.py", line 1269, in <module>
    main(sys.argv[1:])
  File "/opt/meza/src/scripts/meza.py", line 64, in main
    print( "Meza " + version.strip() )
           ~~~~~~~~^~~~~~~~~~~~~~~~~
TypeError: can only concatenate str (not "bytes") to str
[root@localhost opt]# python3.11 meza/src/scripts/meza.py --version
Meza b'39.0.0-16-gcd9359f'
Commit b'cd9359f36e816e0f9192c28833bb7eea1d19ddc4'
Mediawiki EZ Admin

It appears that some extraneous 'b' is being output. Is that 'b' for byte?

Edit: YES, it is the Python representation of a byte sequence. The change in handling of bytes vs strings in Python 3 (where it's now more strict) is the cause of this (compatibility) issue.

@freephile
Copy link
Owner Author

It doesn't seem to matter whether I use Python 3.6.8 or Python 3.11, I still get the 'b' (byte) output even when trying to format() or use text=True in subprocess.check_output()

Even trying 'f strings' still gives the same output

print( f"Meza {version}" )
print( f"Commit {commit}" )
print( "Mediawiki EZ Admin" )

Meza b'39.0.0-16-gcd9359f\n'
Commit b'cd9359f36e816e0f9192c28833bb7eea1d19ddc4\n'
Mediawiki EZ Admin

@freephile
Copy link
Owner Author

freephile commented Jan 24, 2024

Recap

Here's what you get with an unmodified meza.py on Python 3.6.8

[root@localhost opt]# python3 ./meza/src/scripts/meza.py --version
Traceback (most recent call last):
  File "./meza/src/scripts/meza.py", line 1269, in <module>
    main(sys.argv[1:])
  File "./meza/src/scripts/meza.py", line 64, in main
    print( "Meza " + version.strip() )
TypeError: must be str, not bytes

And Python 3.11 gives pretty much the same error:

[root@localhost opt]# python3.11 ./meza/src/scripts/meza.py --version
Traceback (most recent call last):
  File "/opt/./meza/src/scripts/meza.py", line 1269, in <module>
    main(sys.argv[1:])
  File "/opt/./meza/src/scripts/meza.py", line 64, in main
    print( "Meza " + version.strip() )
           ~~~~~~~~^~~~~~~~~~~~~~~~~
TypeError: can only concatenate str (not "bytes") to str

The best I've come up with so far is to wrap a format call in the concatenation:

print( "Meza " + format(version.strip()) )
print( "Commit " + format(commit.strip()) )
print( "Mediawiki EZ Admin" )
print( "" )
sys.exit(0)

produces (for both Python 3.6.8 and 3.11)

Meza b'39.0.0-16-gcd9359f'
Commit b'cd9359f36e816e0f9192c28833bb7eea1d19ddc4'
Mediawiki EZ Admin

In Python 3.11, we can add the text=True argument to subprocessl.check_output and it works! without even using format() in the concatenation:

import subprocess
version = subprocess.check_output( ["git", "--git-dir={}/meza/.git".format(install_dir), "describe", "--tags" ], text=True )
commit = subprocess.check_output( ["git", "--git-dir={}/meza/.git".format(install_dir), "rev-parse", "HEAD" ], text=True )
print( "Meza " + version.strip() )
print( "Commit " + commit.strip() )
print( "Mediawiki EZ Admin" )
print( "" )
output = subprocess.check_output(["python", "--version"], text=True)
print(output)

(note how the system Python version is 3.6.8, but we run the code with python3.11 ./meza/src/scripts/meza.py --version)

Meza 39.0.0-16-gcd9359f
Commit cd9359f36e816e0f9192c28833bb7eea1d19ddc4
Mediawiki EZ Admin

Python 3.6.8

But that code produces an error in Python 3.6.8

python3 ./meza/src/scripts/meza.py --version
Traceback (most recent call last):
  File "./meza/src/scripts/meza.py", line 1271, in <module>
    main(sys.argv[1:])
  File "./meza/src/scripts/meza.py", line 62, in main
    version = subprocess.check_output( ["git", "--git-dir={}/meza/.git".format(install_dir), "describe", "--tags" ], text=True )
  File "/usr/lib64/python3.6/subprocess.py", line 356, in check_output
    **kwargs).stdout
  File "/usr/lib64/python3.6/subprocess.py", line 423, in run
    with Popen(*popenargs, **kwargs) as process:
TypeError: __init__() got an unexpected keyword argument 'text'

@freephile
Copy link
Owner Author

freephile commented Jan 24, 2024

So, the open question is

  1. whether Python must be upgraded;
  2. or is there a better approach to formatting and concatenating bytes and strings;
  3. or is the 'ugly' output good enough?.

Upgrading Python is discussed here

freephile added a commit that referenced this issue Jan 24, 2024
By adding .decode() to the byte objects, we can concatenate with strings in Python 3.6.8

Later versions of subprocess.check_output() can return text if you want, but not in this version.
@freephile
Copy link
Owner Author

freephile commented Jan 25, 2024

Responses:

  1. Python does not need to be upgraded... at least not to solve this problem. (The discussion about Upgrading Python addresses the big picture.)
  2. There is a "better approach" to formatting and concatenating bytes and strings in Python 3.x. Python 3.x is more strict about mixing types and so in this case we need to use decode(). Documentation for bytes.decode in Python 3.6.x
    See best practices for Ansible and Python
  3. No, incorrect representation of the desired data is unacceptable.

@rjt
Copy link

rjt commented Jan 25, 2024

Progress:)

freephile added a commit that referenced this issue Feb 15, 2024
By adding .decode() to the byte objects, we can concatenate with strings in Python 3.6.8

Later versions of subprocess.check_output() can return text if you want, but not in this version.

This work  was performed for NASA GRC-ATF by WikiWorks per NASA Contract  NNC15BA02B.
@freephile freephile self-assigned this Mar 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working python Python programming
Projects
None yet
Development

No branches or pull requests

2 participants