Python Popen grep

2024/9/22 19:39:50

I'd like Popen to execute:

grep -i --line-buffered "grave" data/*.txt

When run from the shell, this gives me the wanted result. If I start, in the very same directory where I test grep, a python repl and follow the instruction from the docs, I obtain what should be the proper argument list to feed Popen with:

['grep', '-i', '--line-buffered', 'grave', 'data/*.txt']

The result of p = subprocess.Popen(args) is

grep: data/*.txt: No such file or directory

and if I try p = subprocess.Popen(args, shell=True), I get:

Usage: grep [OPTION]... PATTERN [FILE]...
Try `grep --help' for more information.

Any help on how to perform the wanted process? I'm on MacOS Lion.

Answer

If you type * in bash the shell expands it to the files in the given directory before executing the command. Python's Popen does no such thing, so what you're doing when you call Popen like that is telling grep there is a file called *.txt in the data directory, instead of all the .txt files in the data directory. That file doesn't exist and you get the expected error.

To solve this 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)

Which gets translated to:

subprocess.Popen(['/bin/sh', '-c', 'grep -i --line-buffered "grave" data/*.txt'])

As explained in the documentation of Popen.

You have to use a string instead of a list here, because you want to execute /bin/sh -c "grep -i --line-buffered "grave" data/*.txt" (N.B. quotes around the command, making it a single argument to sh). If you use a list this command is run: /bin/sh -c grep -i --line-buffered "grave" data/*.txt, which gives you the output of simply running grep.

https://en.xdnf.cn/q/71913.html

Related Q&A

Url structure and form posts with Flask

In Flask you write the route above the method declaration like so: @app.route(/search/<location>/) def search():return render_template(search.html)However in HTML the form will post to the url in…

How can I simulate a key press in a Python subprocess?

The scenario is, I have a Python script which part of it is to execute an external program using the code below:subprocess.run(["someExternalProgram", "some options"], shell=True)An…

Difference between pd.merge() and dataframe.merge()

Im wondering what the difference is when you merge by pd.merge versus dataframe.merge(), examples below:pd.merge(dataframe1, dataframe2)anddataframe1.merge(dataframe2)

ctypes in python crashes with memset

I am trying to erase password string from memory like it is suggested in here.I wrote that little snippet:import ctypes, sysdef zerome(string):location = id(string) + 20size = sys.getsizeof(string)…

Python __del__ does not work as destructor? [duplicate]

This question already has answers here:What is the __del__ method and how do I call it?(5 answers)Closed 4 years ago.After checking numerous times, I did find inconsistent info about the topic.In some…

How to set default button in PyGTK?

I have very simple window where I have 2 buttons - one for cancel, one for apply. How to set the button for apply as default one? (When I press enter, "apply" button is pressed)However, I wa…

Can Python recognize changes to a file that it is running interactively?

I was doing some troubleshooting and I was curious if it is possible to run a Python script interactively, change a function defined in the script, save the file, then have the interactive shell recogn…

How to use FTP with Pythons requests

Is it possible to use the requests module to interact with a FTP site? requests is very convenient for getting HTTP pages, but I seem to get a Schema error when I attempt to use FTP sites. Is there …

How to find a best fit distribution function for a list of data?

I am aware of many probabilistic functions builted-in Python, with the random module. Id like to know if, given a list of floats, it would be possible to find the distribution equation that best fits t…

How to use peewee limit()?

With Peewee Im trying to use limit as follows:one_ticket = Ticket.select().limit(1) print one_ticket.count()This prints out 5 however. Does anybody know whats wrong here?