0

I have a python (v2.7) script that needs to clear the contents of a file before writing to it (if it exists). I'm able to execute the 'same' command on the command line without issue, but I get a either a python or bash error when calling variations of this command from python. Don't know what I'm missing.

Ultimate question: How can I create an empty file (or clear, if it exists) using a system call from Python (v2.7)?

Bash (successfully creates empty or clears existing file)

$ > test.txt
$ ls -l test.txt
-rw-rw-r--+ 1 <owner> <group> 0 Feb  9 11:26 test.txt

Python (w/o `shell=True'; fails with error)

I get the following error without using shell=True: OSError: [Errno 2] No such file or directory. Another post suggests I shouldn't get this error if I pass all arguments as individual string parameters. Not sure why I get this error.

$ python
>>> import subprocess
>>> subprocess.call(['>', 'test.txt']) # Same result w/ single/double quotes
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/subprocess.py", line 172, in call
    return Popen(*popenargs, **kwargs).wait()
  File "/usr/lib/python2.7/subprocess.py", line 394, in __init__
    errread, errwrite)
  File "/usr/lib/python2.7/subprocess.py", line 1047, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory

Python (w/ `shell=True'; fails with error)

I tried adding shell=True per suggestions from the other post (shouldn't be security risk since the command is static), but I get the following bash error: Syntax error: end of file unexpected. I thought it might need an ending ; (maybe because of how python makes the call?), so I tried two adding a ; argument with the same end result.

$ python
>>> import subprocess
>>> subprocess.call(['>', 'test.txt'], shell=True) # Same result w/ single/double quotes
test.txt: 1: test.txt: Syntax error: end of file unexpected
2
>>> import subprocess
>>> subprocess.call(['>', 'test.txt', ';'], shell=True)  # Same result w/ single/double quotes
test.txt: 1: test.txt: Syntax error: end of file unexpected
Mark Ebbert
  • 441
  • 3
  • 13
  • Does it work when you use an actual command instead of just a redirection, with, say, `subprocess.call([':', '>', 'test.txt'])`? – Jens Feb 09 '22 at 17:11
  • 1
    Passing a single string would be `.call('> test.txt', shell=True)` but can't you just `open('test.txt', 'w')` and get the same result? –  Feb 09 '22 at 17:20
  • @Jens: I tried your suggestion (e.g., `subprocess.call(["cat 'hello'", ">", "test.txt"])`, but get the same `OSError: [Errno 2] No such file or directory`. – Mark Ebbert Feb 09 '22 at 17:57
  • @KarlThornton, yes, that does indeed work. I didn't realize that re-opening the file with `python` would accomplish the same objective. I will use this approach, but understanding why my approach doesn't work would still be helpful. I think @MOStudios answered part of it. – Mark Ebbert Feb 09 '22 at 18:00
  • @MarkEbbert No, that's a *different* error. You should not use shell quoting characters when you assemble argument lists. What happens when you run `subprocess.call("echo hello > test.txt")`? – Jens Feb 09 '22 at 18:24
  • You seem to be going a very roundabout way to your stated objective. Depending on the access mode you specify when you open the file, Python will *automically* clear its contents. Write-only modes based on `'w'` and read/write modes based on `'w+'` will do this (and this is the primary difference between `'w+'` and `'r+'`). Why do you want to involve `system()`? – John Bollinger Feb 09 '22 at 19:03
  • I am of course assuming that you open the file with `open()`. – John Bollinger Feb 09 '22 at 19:10

1 Answers1

1

shell=True Error

When using this, the command given is meant to be formatted as ONE string

The command string given is then interpreted as a raw shell command

The correct usage should be like this:

>>> import subprocess
>>> subprocess.call('> test.txt', shell=True)
0
>>> 
# There will now be an empty file called
# 'test.txt' in the same directory 

shell=False Error

The command you are running is meant to be ran on top of a shell, but when using this way, it tries to run your string by calling it as a command found in your PATH

However, I don't know how to solve this part of the issue for your case.

MOStudios
  • 540
  • 3
  • 12
  • that is helpful. I didn't see that `shell=True` requires a single string. Kind of strange, but submitting as one string worked! **You'll want to update your answer to show the call as one string**. It's presently formatted as multiple arguments like I was doing. The `;` character was also not needed. – Mark Ebbert Feb 09 '22 at 18:02
  • oh yeah, sorry about that, i guess when i formatted it as one string in the answer, it didn't save, i'll change it anyway – MOStudios Feb 09 '22 at 18:55