Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why I got "sh: 1: Syntax error: Unterminated quoted string" when I run my Python program?

Tags:

python

shell

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.

like image 291
maemual Avatar asked Oct 16 '25 14:10

maemual


2 Answers

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]
like image 117
Johnsyweb Avatar answered Oct 18 '25 03:10

Johnsyweb


@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

like image 27
tripleee Avatar answered Oct 18 '25 04:10

tripleee



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!