1

I am trying to pass the output of a shell script into python, it works when I do not have unicode characters inside the string that should be returned. The bash script that gets the currently played music:

player_status=$(playerctl status 2> /dev/null)
if [[ $? -eq 0 ]]; then
    metadata="$(playerctl metadata title 2> /dev/null)"
else
    metadata="No music playing"
fi

# Foreground color formatting tags are optional
if [[ $player_status = "Playing" ]]; then
    echo "$metadata"|cut -c -65       # when playing
elif [[ $player_status = "Paused" ]]; then
    echo "$metadata"|cut -c -65        # when paused
else
    echo "$metadata"|cut -c -65       # when stopped
fi

The python script that uses the return value of the script above

def getMusicName():
        music_name = os.popen('bash /home/nep/Self\ Script/now-playing.sh').read()
        return music_name

The error

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe2 in position 64: invalid continuation byte

Finally the name of the music that it was trying to decode:

IZANAGI 【 イザナギ 】 ☯ Japanese Trap & Bass Type Beat ☯ Trapanese Hip Hop Mix

As a sidenote, this is on a Linux system, but I do not think it should make a difference, also if I run the shell script alone it returns the name like this:

IZANAGI 【 イザナギ 】 ☯ Japanese Trap & Bass Type Beat �
                                                         ⏎   
2
  • Can you try extracting data from the process one char at time to see which one breaks? Commented Apr 28, 2021 at 14:35
  • @AndreaRossini The invalid character was at position 64 according to the error msg, so the 64th character from the output of the script means it was the second line which was a blank line with so I guess it was full of junk characters, but actuallz I solved it somewhat according to your debug process, thank you <3 Commented Apr 28, 2021 at 15:21

1 Answer 1

3

To be sure the metadata is using proper UTF-8 encoding, you can filter the output of playerctl with iconv -ct UTF-8//TRANSLIT:

Here is your improved script:

#!/usr/bin/env bash

if player_status="$(playerctl status 2>/dev/null)"; then
  metadata="$(playerctl metadata title 2>/dev/null | iconv -ct UTF-8//TRANSLIT)"
else
  metadata="No music playing"
fi

# Foreground color formatting tags are optional
case "$player_status" in
  Playing)
    printf '%.65s\n' "$metadata" # when playing
    ;;
  Paused)
    printf '%.65s\n' "$metadata" # when paused
    ;;
  *)
    printf '%.65s\n' "$metadata" # when stopped
    ;;
esac
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you, even tho I solved it with redoing the whole script in python I used this improved one because it feels easier to modify than the one I did, thank you
@SyntaxKills Using an MPRIS library within Python would be a good alternate option rather than chaining Python behind a Bash script that runs an external command. Example: pypi.org/project/mpris2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.