If you type * in bash, the shell expands it to the files in this directory before executing the command. Python Popen does not do this, so what you do when you call Popen, as grep says, is a file named *.txt in the data directory, and not all .txt files in the data directory. This file does not exist and you will receive the expected error.
To solve this problem, you can tell python to run the command through the shell by passing shell=True to Popen:
subprocess.Popen('grep -i --line-buffered grave data/*.txt', shell=True)
What translates to:
subprocess.Popen(['/bin/sh', '-c', 'grep -i --line-buffered "grave" data/*.txt'])
As explained in the Popen documentation .
Here you should use a string instead of a list because you want to execute /bin/sh -c "grep -i --line-buffered "grave" data/*.txt" (NB quotes around the command, making it the only argument to sh ) If you use a list, this command runs: /bin/sh -c grep -i --line-buffered "grave" data/*.txt , which gives you the result of a simple grep run.
source share