3

I want to count how many lines of code I have written.

Here is the Python code:

import os
import sys

EXT = ['.c','.cpp','.java','.py']

def main():
    l = []
    if os.path.isdir(sys.argv[1]):
        for root, dirs, files in os.walk(sys.argv[1]):
            l.extend([os.path.join(root, name) for name in files])
    else:
        l.append(sys.argv[1])

    params = ["'"+p+"'" for p in l if os.path.splitext(p)[1] in EXT]

    result = os.popen("wc -l %s "%" ".join(params)).read()
    print result

if __name__ == '__main__':
    main()

Before this, it was running as expected. But today, it give me this error:

sh: 1: Syntax error: Unterminated quoted string

I don't know what happened.

nsane
  • 1,468
  • 2
  • 20
  • 29
maemual
  • 41
  • 1
  • 1
  • 5

3 Answers3

4

Your Python script is missing a shebang line. Add the following to the top of your file:

#!/usr/bin/env python

Then you should be able to run the following, assuming your script is at /path/to/your_script.py and it has the executable bit set:

/path/to/your_script.py arg1 arg2 [...]

Alternatively:

python /path/to/your_script.py arg1 arg2 [...]

Update following comments

I suspect what has changed is that a source file containing a ' in its name has been added to the directory you are checking and the shell is choking on this.

You could add the following function to your program:

def shellquote(s):
    return "'" + s.replace("'", "'\\''") + "'"

[Lifted from Greg Hewgill's answer to How to escape os.system() calls in Python? .]

And call it like this:

params = [shellquote(p) for p in l if os.path.splitext(p)[1] in EXT]
Community
  • 1
  • 1
Johnsyweb
  • 121,480
  • 23
  • 172
  • 229
  • @maemual: The same "wrong" or a different "wrong"? What is the output of `which python` (and `python --version`)? – Johnsyweb Aug 31 '13 at 04:07
  • which python /usr/bin/python, python --version 2.7.3 – maemual Aug 31 '13 at 04:27
  • To be clear, the first line is to be added to the top of the script itself; the second and third are commands to be executed from the shell. And see [this question](http://unix.stackexchange.com/q/29608/10454) and [my answer](http://unix.stackexchange.com/a/29620/10454) for discussion of the `#!/usr/bin/env` trick; the alternative is `#!/usr/bin/python` – Keith Thompson Aug 31 '13 at 04:36
  • @maemual: Then I have a new theory and have updated my answer. – Johnsyweb Aug 31 '13 at 05:29
  • Yes, it's the true problem.THX! – maemual Sep 01 '13 at 02:59
1

@Johnsyweb's updated answer seems to have the correct diagnostic, but the correct fix is to not use a shell to invoke wc. Try something like this instead:

cmd = ['/bin/wc', '-l'] # Need full path!
[cmd.extend(p) for p in l if os.path.splitext(p)[1] in EXT]
result = os.popen2(cmd).read()

Note that the subprocess module is the recommended solution now. Switching to that requires a less intrusive change to your current code, though; see http://docs.python.org/2/library/subprocess.html#replacing-os-popen-os-popen2-os-popen3

tripleee
  • 139,311
  • 24
  • 207
  • 268
  • 1
    Nice fix, but why are you creating a list comprehension here? – Johnsyweb Aug 31 '13 at 09:20
  • 1
    @Johnsyweb: Lazy copy/paste; not at my computer so didn't want to change more than absolutely necessary. Feel free to edit, or adopt into your answer. – tripleee Aug 31 '13 at 13:56
0

Looks like your Python program was parsed like a shell script. Add something like this at the header to indicate where your Python is:

#!/usr/bin/python

or you just run python a.py.

Santosh Kumar
  • 22,275
  • 18
  • 59
  • 100
user650749
  • 170
  • 2
  • 13