I have been trying to pass a string from stdin to a python script, but I keep getting an error and I can't figure out why.
Here is the script:
import sys
signal = {'A': '.-', 'B': '-...', 'C': '-.-.',
'D': '-..', 'E': '.', 'F': '..-.',
'G': '--.', 'H': '....', 'I': '..',
'J': '.---', 'K': '-.-', 'L': '.-..',
'M': '--', 'N': '-.', 'O': '---',
'P': '.--.', 'Q': '--.-', 'R': '.-.',
'S': '...', 'T': '-', 'U': '..-',
'V': '...-', 'W': '.--', 'X': '-..-',
'Y': '-.--', 'Z': '--..',
'0': '-----', '1': '.----', '2': '..---',
'3': '...--', '4': '....-', '5': '.....',
'6': '-....', '7': '--...', '8': '---..',
'9': '----.'
}
plaintext = ''.join(sys.stdin.readlines())
plaintext2 = 'Hello'
def encode(s):
return ' '.join(signal.get(i.upper()) for i in s)
print('')
print('Results from hardcoded var (plaintext2):')
print('Type:', type(plaintext2))
print('Variable:', plaintext2)
print('Encoded msg:', encode(plaintext2))
print('----------------------------------\n')
print('Results from STDIN var (plaintext):')
print('Type:', type(plaintext))
print('Variable:', plaintext)
print('Encoded msg:', encode(plaintext))
When I run the script I get this:
$ echo Hello | ./morse.py
Results from hardcoded var (plaintext2):
Type: <class 'str'>
Variable: Hello
Encoded msg: .... . .-.. .-.. ---
----------------------------------
Results from STDIN var (plaintext):
Type: <class 'str'>
Variable: Hello
Traceback (most recent call last):
File "./morse.py", line 56, in <module>
print('Encoded msg:', encode(plaintext))
File "./morse.py", line 42, in encode
return ' '.join(signal.get(i.upper()) for i in s)
TypeError: sequence item 5: expected str instance, NoneType found
My question is why do I get that TypeError
when getting the string from the STDIN and it works from a variable in the script.
Edit:
I applied the solutions in the comments from @user2357112 and @Skam.
1 ) Adding some mapping to signal
for extra characters.
2 ) Adding the default character '#' to take care of the unmapped ones:
def encode(s):
return ' '.join(signal.get(i.upper(), '#') for i in s)
Also, thanks @yaccob for your idea about debugging.
def encode(s):
print([str(c) for c in s])
As others have pointed out, there are characters in your string that your code does not know how to handle.
Specifically, signal.get(i.upper())
will return None
if i not in signals
One solution would be to return a default character for all values not found in signals.
def encode(s):
return ' '.join(signal.get(i.upper(), '') for i in s)
Another,
def encode(s):
return ' '.join(filter(lambda x: x.upper() in signal, s))
I like the latter version because IMO it's a little more clear about what the code is actually doing.