Python's subprocess.check_output( ) - python

I'm working with python's subprocess.check_output() and I'm using it to run a python file that takes certain attributes (like fileName, title, etc..). Everything works fine however, I decided to pass in a string variable instead of an actual string. This doesn't work and I'm not sure why. Does anyone see something that I don't?
import textFile
import upload
import subprocess
def upload(fileName):
arr = []
bunny = "big_buck_bunny.flv" #this is the variable
arr = textFile.readLine(fileName)
size = textFile.getLines(fileName)
i = 0
while(i < size):
f = open("upload.py-oauth2.json", 'w').close()
textFile.append("C:\\Users\\user1\\Desktop\\tester\\upload.py-oauth2.json",arr[i])
#This below is where i would like to pass in a variable
subprocess.check_output('python upload.py --file="C:\\Users\\...\\anniebot\\' + bunny)
i+=1
upload("C:\\Users\\user1\\Desktop\\tester\\accountList.txt")
So I pretty much would like to change the path constantly. The problem is, I cant figure out a way to get subprocess to work without passing in a fixed string.
i would like to do something like:-
subprocess.check_output('python upload.py --file="C:\\Users\\user1\\Videos\\anniebot\\" + bunny --title="title" --description="testing" --keywords="test" --category="22" --privacyStatus="public"')

Do you mean:
subprocess.check_output('python upload.py --file="C:\\Users\\...\\anniebot\\' + bunny + '" --title= ...')
So basically concatenate the string using the single quote instead of the double quote you are using.

Related

Python string instead of unknown module name

Elham Here, I have made a simple code to something like this:
It accepts a string (name) from user
then it do some customization to the string (turn lowercase and replacing space with "_"{under score})
then after customization, it will search for a file with same name as string
then display the content of file. here is its code:
import coder
import time
import calc
mainfunc = ["clears", "action mode"]
main_loop = "main"
coder.clear_screen()
while main_loop == "main":
ask = input("BOT: You say? > ")
mask = ask.replace(" ", "_")
if mask == mainfunc[0]:
print("\n" * 100)
coder.clear_screen()
else:
prt = open(mask, "r")
pr = prt.read()
print(pr)
prt = open(mask, "r")
pr = prt.read()
print(pr)
this is what I can with text, and I have plan to do same thing with some python modules (like instead of displaying its code, it should execute the code), which search for the module name with the string given by user! its like unknown module to be executed with name of string.
I have tried getattr and others like {}.format, ...
but non worked. I have researched the documentation section of functions and modules, but didn't found anything to help or it was too confusing while I don't know name of what I am searching for : (
so if you know the fix, please send the code! You will save my life (I have made a bet with a friend on this :p
-thanks
Python's exec function will execute a string as raw code, which lets you do something like this:
module = input("Enter module to import:")
exec("import " + module)

Python: interpreter says "None" after parsing file

I've written a simple interpreter with Python for a programming language I've created. I have a little problem though: when I try to read a file, so the code can be interpreted, Python says None.
Here's the interpreter code:
import sys
class Interpret:
def read(self, cmd):
tokens = cmd.split("\n")
for i in range(0, len(tokens)):
self.parse(tokens[i])
def parse(self, cmd):
if cmd.startswith("print(") and cmd.endswith(")"):
cmd = cmd[6:]
cmd = cmd[:-1]
return(cmd)
interpret = Interpret()
code = open(sys.argv[1], 'r')
print(interpret.read(str(code)))
Here's the code in the file I want to read: print(Hi)\n (Yes, there's a newline there, not the characters \n)
So, here's what happened in CMD:
> python interpreter.py test.tl
None
It should output Hi, but it doesn't work properly. I think it has something to do with the last two lines of the interpreter code, but I'm not completely sure.
You're just calling self.parse and not using its return value and, given that self.parse doesn't output anything and read returns nothing (None), you're getting None as a result.
You may want your read to yield self.parse(tokens[i]) on each iteration, thus making it a generator, and then do something like this:
for data in interpret.read(str(code)):
print(data)
One of your problems is this line:
code = open(sys.argv[1], 'r')
open returns a file object, not the content of the file. Instead, do:
with open(sys.argv[1], 'r') as f:
code = f.read()
On to the next issue:
for i in range(0, len(tokens)):
self.parse(tokens[i])
There is no reason to iterate over the range of a len, ever. Just iterate over the tokens:
for token in tokens:
self.parse(token)
That your code prints None is (as ForceBru has written already) due to the fact that you're printing the return value of a method that returns nothing. Just call interpret.read(str(code)) directly, without wrapping print around it.
After applying all these fixes, to make your code work either do what ForceBru says and yield self.parse(token), or, for testing purposes just print inside of parse:
def parse(self, cmd):
if cmd.startswith("print(") and cmd.endswith(")"):
cmd = cmd[6:]
cmd = cmd[:-1]
print(cmd)
Then, your code works for me with print(Hi)\n in the test.tl file.

Python 3 long filename as argument (python splits it)

I've been having a problem with taking a command line argument on windows that has a long filename and passing it to a function.
In short the long filename containing spaces is split into separate parts.
I made a fudged together bit of code to give me the command line as a whole, but it's far from ideal as although it works for multiple parameters it doesn't work for LFNs with spaces.
(the cludge was made for a different script, I've just copied it across to this one)
I've been searching for hours on google trying to figure this out as surely someone else has solved this.
I've tried using ArgParse but couldn't get that to give me the filename without splitting it either.
Would someone be good enough to show me some code that demonstrates getting the command line exactly as is (minus the script name) and also getting a full filename.
Thanks,
Adam
[edit..]
I tried putting quotes around it and it failed still. I know from testing the code that it splits the input on the spaces and removes the quotes.
example from a different test:
test.py code:
import sys
print ('Number of arguments:', len(sys.argv), 'arguments.')
print ('Argument List:', str(sys.argv))
for x in range(0, len(sys.argv)):
print("->" + sys.argv[x])
output:
H:\bin>test "test lfn.txt"
Number of arguments: 3 arguments.
Argument List: ['H:\\bin\\test.py', ' test', 'lfn.txt']
->H:\bin\test.py
-> test
->lfn.txt
#
[edit 2]
I think it's a Python on Windows bug as double quoting works, sort of:
H:\bin>test ""test lfn.txt""
Number of arguments: 2 arguments.
Argument List: ['H:\\bin\\test.py', ' "test lfn.txt"']
->H:\bin\test.py
-> "test lfn.txt"
original code posted below.
###############################################################################
# Renames a single file to ISO date format: YYYYMMDD-HHMMSS #
###############################################################################
import datetime, os, sys
def error_filename():
print("filename doesn't exist maybe.")
sys.exit(1)
def error_args():
print("Renames a single file to ISO date format: YYYYMMDD-HHMMSS")
print("Requires 1 parameter, the filename to rename")
sys.exit(2)
def error_rename():
print("Unable to rename")
sys.exit(3)
cmds = ""
for x in range(1, len(sys.argv)):
cmds = cmds + sys.argv[x]
cmds = cmds.strip()
if cmds != "":
d = datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
if os.path.isfile(cmds):
fn = cmds.split(os.extsep)
fn[0]=d
newname = d + "." + fn[1]
print(cmds + " -> " + newname)
try:
os.rename(cmds, newname)
except:
error_rename()
else:
error_filename()
else:
error_args()
The error I was having was because Windows 7 was previously defaulting to opening python files in an editor, I changed it manually in the registry to open with python. By doing a clean install on a different machine and letting the python installer set up the path etc it worked fine. The problem lies with a windows registry setting.

Python BUG or I don't get how encoding works? len, find, and re.search do nothing with no empty, successful subprocess.communicate() execution result

For a reason I cannot understand I cannot do nothing with the output of Popen.communicate, except for print it to terminal.
If I save the output to a variable, the variable contains the text, because I can print it to terminal too, but len returns 0, re.search match nothing, and find always returns -1.
The offending function:
#!/usr/bin/env python
# coding: utf-8
import os
import sys
import getopt
import subprocess
import os.path
import re
def get_video_duration (ifile):
p = subprocess.Popen(["ffprobe", ifile], stdout=subprocess.PIPE)
info_str = p.communicate()[0].decode(sys.stdout.encoding)
print(info_str) # for debug, the information about the file prints ok
duration_start = info_str.find("Duration")
# duration_start = "AJDKLAJSL Duration:".find("Duration"), this test was ok
duration_end = info_str.find("start", duration_start)
number_start = info_str.find(" ", duration_start, duration_end) + 1
number_end = info_str.find(",", number_start, duration_end)
temp = info_str[number_start:number_end].split(":")
return int(temp[0]) * 60 * 60 + int(temp[1]) * 60 + int(temp[2])
I attempted different variations. Like do not use .decode(), change find for a single re.search, implement my own find by iterating each character (the problem is that I need len for this, and len always returns 0 for that particular string/byte_array).
It is a bug of some sort or I am doing something wrong about the string encoding. I cannot figure what exactly is the problem. Any help appreciated.
Ubuntu 12.10 64 bits
Python 2.7
You're not doing anything wrong with encoding. Your problem is that ffprobe sends its output (including the duration info you're looking for) to stderr, not stdout. Do this and you should be fine:
def get_video_duration (ifile):
p = subprocess.Popen(["ffprobe", ifile], stderr=subprocess.PIPE)
info_str = p.communicate()[1].decode(sys.stderr.encoding)
The reason your print() call seems to be working is that it's printing nothing (because info_str truly is empty)... but the stderr output is being dumped to the console, which gives you the illusion that what you're seeing is the result of your print() call.

python subprocess read stdout as it executes

one of my function in the program checks the md5sum of hashfile
def check():
print "checking integrity status.."
md5 = subprocess.Popen(["md5sum", "-c", hashfile],shell=False, stdout=subprocess.PIPE)
#fopen = open(basefile, "r")
for f in md5.stdout.readlines():
fc = f.rstrip("\n")
sys.stdout.write("\rChecking..." + fc)
sys.stdout.flush()
now what happens is that the whole command is first executed and then for loop reads from md5 using md5.stdout.readlines, as such it is not dynamic i.e. i dont get the output as the command is executed....is there a way i can get the output while the command is in execution...
fixed using glglgl's answer:
def check():
print "checking integrity status.."
md5 = subprocess.Popen(["md5sum", "-c", hashfile],shell=False, stdout=subprocess.PIPE)
#fopen = open(basefile, "r")
fc = "NULL"
i = 0
for f in iter(md5.stdout.readline, ''):
k = fc
fc = f.rstrip("\n")
if "FAILED" in fc:
print fc
i = i + 1
sys.stdout.write("\rChecking... "+ str(i)+ " " + fc + (' ' * (len(k) - len(fc))) )
sys.stdout.flush()
Of course. There are several ways.
First, you could work with md5.stdout.read(), but there you would have to do line separation by yourself.
Then, you could operate with the file object md5.stdout as iterator. But there seems to be an issue with buffering, i. e. you don't get the results immediately.
And then there is a possibility to call md5.stdout.readline() repeatedly until it returns ''.
The third way is to be preferred in this case; I would suggest it to do like this:
...
for f in iter(md5.stdout.readline, ''):
fc = f.rstrip("\n")
sys.stdout.write("\rChecked " + fc)
sys.stdout.flush()
I have also changed the output text, as there is only an output if che check is done already.
If that is not what you want, but rather really haveing every output captured separately, you should switch to point 1. But that makes it more complicated. I will think about a solution on indication that it is wanted.
There, one must consider the following points:
read() blocks, so one should read byte for byte (quite ugly).
There is the question what should be output and when should there be a intermitting output.
The original poster is correct that hashlib is not available in Python 2.4, however, the md5 library is available. Example workaround:
try:
# Python 2.5 and up.
import hashlib
md5Hash = hashlib.md5
except ImportError:
# Python 2.4 and below.
import md5
md5Hash = md5.new
somedata = 'foobar'
hashstring = md5Hash (somedata).hexdigest ()
What is the file size?
Popen creates a new child process to run the command. Maybe it finishes before you run the for loop.
You can check if the "subprocess" has finished looking returncode attribute (in your code: md5.returncode)

Categories