I'm trying to run a program using a python program. The program is supposed to run the program, get the output, and write it to a text file. The program being run (which is an exe), takes one argument, so I used:

subprocess.call(["path", "arg"])

This works fine, but the problem is when I write it to the file I get:

TypeError: argument 1 must be string or read-only character buffer, not int

I tried:

str(subprocess.call(["path", "arg"]))

Theres no error with this, but it only writes zero to the text file, not the real output of the program. Is there any way to either convert the output to a string or another command where it already is string?

You can do a thing inside the program where you can append arguments. It goes something like:

import sys
sys.argv.append("ooh look an argument")
#now there is an argument!

No, I'm sorry if i wasn't clear. I'm writing a program in python but I need to call an exe with an argument in that program.

I don't know what that "it" is you are trying to write to the file. You seem to want to write the output of the program being run, but I don't think you can do that with .call() which just returns the final status of the program run, which is an integer and needs to be converted to a string to write out, but that's not what you really wanted anyway...

Try this example, substituting your actual command and arguments:

>>> p = subprocess.Popen(["dir", "/etc"], stdout=subprocess.PIPE)
>>> for x in p.stdout:
...     print x[:-1]   # Trim tailing \n with [:-1] slice
...
DIR_COLORS    defaults  mtab      postinstall  profile.d  services  termcap
alternatives  group     networks  preremove    protocols  setup
bash.bashrc   hosts     passwd    profile      rpm        skel
>>> p.stdout.close()

If this suggestion is off the mark, perhaps you could post some actual code and explain what's going wrong. Fewer ambiguous pronouns that way.

Comments
good, clean, simple, I like it

It's basically a program to md5 hash a password. The code is pretty simple:

import subprocess

file = open("hash.txt", 'a')
code = subprocess.Popen(["md5.exe", "-da"], stdout=subprocess.PIPE)
file.write(code)

Basically, It opens the file where the final hash will be stored, then sets the variable code equal to the output of the program, then writes it to a file. md5.exe is the program I'm using which is in the same directory as the python file. -d is the command used to hash, and whatever comes after that is what will be hashed. Right now its only going to hash the letter a simply for testing purposes. The problem is that when it writes to the file I get:

Traceback (most recent call last):
File "C:\Documents and Settings\Gulshan\My Documents\Python Scripts\2md5\2md5.py", line 11, in <module>
file.write(code)
TypeError: argument 1 must be string or read-only character buffer, not Popen
0CC175B9C0F1B6A831C399E269772661

If you can't fix the problem with this much information, I would be happy to upload the md5.exe program so you can actually test it out. Just ask.

file.write(code) is wrong. Replace with:

for line in code.stdout:  # code.stdout is handle to subprocess output
    file.write(line)

This should get you closer.

Just in case it helps, there is a built in way to get md5 hashes within python. check out the hashlib library.

import hashlib

myhash = hashlib.md5('this is a sentence')
print myhash.hexdigest()

myfile = open('somefile.txt','r')
myhash = hashlib.md5(myfile.read())
print myhash.hexdigest()

One more thing: you probably need to add code.stdout.close() after you are done with the subprocess output. In this case, probably right after the for loop that writes out the lines. That file was opened for you in the .Popen() call and I don't think it gets closed automatically.

Your program will work with or without the .close() but it's good form to close files when you are done with them. Otherwise (for example) you may find your program runs for a while then mysteriously stops working. Not that I'm speaking from experience or anything ;)

@mn_kthompson:
Thanks, I'll try it out.

@BearofNH:
Thanks, but just to make sure, where would you put the close function in this code:

import subprocess

file1 = open("1 Character Database.txt", 'a')
for a in range(33,255):
        string = chr(a)
	argument = "-d" + string
	code = subprocess.Popen(["md5.exe", argument], stdout=subprocess.PIPE)
	for line in code.stdout:
                file1.write(string + " " + line)
        code.stdout.close()

or here:

import subprocess

file1 = open("1 Character Database.txt", 'a')
for a in range(33,255):
        string = chr(a)
	argument = "-d" + string
	code = subprocess.Popen(["md5.exe", argument], stdout=subprocess.PIPE)
	for line in code.stdout:
                file1.write(string + " " + line)
code.stdout.close()

So basically directly after the writing loop, or after everything is done in the main body?

This article has been dead for over six months. Start a new discussion instead.