subprocess error in python - python

I'm using PDFminer to convert pdf to html file.
Wrong Code:
def pdf2html(filename, path):
outfile_name = filename.split('.')[0] + '.html'
cmd = ['pdf2txt.py', '-o', path + outfile_name, path + filename]
print ' '.join(cmd)
subprocess.call(cmd, shell=True)
filename = "040214_MOOCs.pdf"
path = "/Users/andy/GoogleDrive/Debate/intelligencesquaredus/data/"
pdf2html(filename, path)
The above code is supposed to run "pdf2txt.py -o /Users/andy/GoogleDrive/Debate/intelligencesquaredus/data/040214_MOOCs.html /Users/andy/GoogleDrive/Debate/intelligencesquaredus/data/040214_MOOCs.pdf"
in the shell.
But there's no output(040214_MOOCs.html) using above code. If I run the command in shell, it generates output with no problem.
Then I tried following script and it works, the only difference is using os.system instead of subprocess.call:
def pdf2html(filename, path):
outfile_name = filename.split('.')[0] + '.html'
cmd = ['pdf2txt.py', '-o', path + outfile_name, path + filename]
print ' '.join(cmd)
os.system(' '.join(cmd))
filename = "040214_MOOCs.pdf"
path = "/Users/andy/GoogleDrive/Debate/intelligencesquaredus/data/"
pdf2html(filename, path)
Also, in wrong code, if I set shell=False, the code also works, why that's the case?
Why subprocess doesn't work in this case while os.system works?
Very confusing, need explanation.

This is likely because of shell mismatch. Can you try running your subprocess call without shell=True?

Related

Errno2 no such file or directory

i've been trying to run sox in a python script but it can't the output file and gives me [errno2]
def AudioToSpectrogram(self, files, pixel_per_sec, height, width):
file_name = ("tmp_{}.png").format(random.randint(0, 100000))
command = "sox -V0 {} -n remix 1 rate 10k spectrogram -y {} -x {} -X {} -m -r -o {}".format(files, height, width, pixel_per_sex, file_name)
p = Popen(command, shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True)
Output, errors = p.communicate()
If errors:
Print(errors)
Image = Image.open(file_name)
Os.remove(file_name)
Return np.array(image)
This is the error it gives
Exception: [errno2] No such file or Directory: 'tmp_47483.png'
I hope you could give me some pointers since i am still new in this field, thanks in advance!
Assuming tmp_47483.png is in fact being created, the problem is likely that the command is placing the file in a different folder and Python can't find it inside the current working directory. The
# manually set the full path (make sure the backslashes are escaped by putting two each)
file_name = f"C:\\Full\\Path\\To\\File\\tmp_{random.randint(0, 100000}.png"
# use the os module to join the path
base_dir = "C:\\Full\\Path\\To\\File"
file_name = os.path.join(base_dir, f"tmp_{random.randint(0, 100000}.png")
# if you want it to appear in the same folder as your script:
CWD = os.path.dirname(os.path.realpath(__file__)) # mostly fool-proof way of getting a script's Current Working Directory
file_name = os.path.join(CWD, f"tmp_{random.randint(0, 100000}.png")
Try these and see if they help. If not, make sure that command is actually working and outputting a file somewhere.

How to write to the beginning of a file when using Python subprocess.call()?

I run the following script:
with open("logfile.txt", 'w') as log_file:
cmd = path + '/somebinary'
log_file.write("Running the command: %s\n" % cmd)
subprocess.call(cmd, shell=True, stdout=log_file, stderr=log_file)
However, the cmd variable gets written to the end of the file and not to the beginning (which I was expecting / hoping for). Can somebody explain to me why and how to prevent this, please?
The operating system performs buffering which can cause output to occur in unexpected order. To force it, flush the file handle after writing.
with open("logfile.txt", 'w') as log_file:
cmd = path + '/somebinary'
log_file.write("Running the command: %s\n" % cmd)
log_file.flush()
subprocess.call(cmd, shell=True, stdout=log_file, stderr=log_file)
Demo: https://ideone.com/U8RPBy
As an aside, you generally want to avoid shell=True; try
cmd = [path + '/somebinary']
...
subprocess.call(cmd, stdout=log_file, stderr=log_file)
and perhaps make sure your PATH is correct instead of hardcoding a specific path.

.svg to .dxf (using Inkscape?)

For a project I need to automate the conversion of plenty .svg-files to .dxf-files for further processing.
Situation: One directory with plenty .svg-files which should be converted to .dxf (no matter if the .dxf files are in the same diretory or in a subfolder, dxf name should be svg name)
I can do that with Inkscape GUI which also works for importing the .dxf files in CAD programs, but as mentioned I need to automate that. (I've only written in Python so far).
My thought: I open the files in Inkscape via command line. Exporting in png-format would be possible via command with following code:
from subprocess import call
import os
svg_dir = "C:\\temp\\layers\\"
files = [svg_dir + i for i in os.listdir(svg_dir) if ".svg" in i]
dir = r"C:\Program Files\Inkscape"
for i in files:
cmdline = "Inkscape -z -f "+ i +" -e "+ i + ".png"
rc = call("start cmd /K " + cmdline, cwd=dir, shell=True)
But I do not really unterstand Inkscape extensions. I only know that I need dxf_outlines.py/.inx in the extension directory. I always need the same export options so could I just rewrite the Python code for that and run it via command in Inkscape?
Or would there be any solution without any extra software like Inkscape in Python? As far as I've seen there isn't.
I came up with a slightly different solution but still made my way to the needed .dxf-files. I saved my figures in Python as .eps-files and could convert them with just one command line with pstoedit.
def eps_to_dxf():
eps_list = [i for i in os.listdir(eps_directory) if ".eps" in i]
work_directory = "C:\Program Files\pstoedit"
for i in eps_list:
input_file = i.split(".")[0]
output_file = input_file + ".dxf"
cmdline = "pstoedit -f dxf_s " + eps_directory + i + " " + eps_directory + output_file
subprocess.check_call(cmdline, cwd=work_directory, shell=True)
This is a Linux command to convert svg file to dxf with Inkscape
python /usr/share/inkscape/extensions/dxf12_outlines.py --output="output.dxf" "input.svg"

Sublime Text custom build system with command line

Does anyone have some experience with custom build systems in Sublime Text 3, especially with python as a base?
At the moment I struggle here with the problem that a extern command line program should be called for baking the file of user.
My current ".sublime-build" looks like this:
{
"target": "convert2libpart",
"selector": "text.xml.gdl"
}
The target is set to the python file,
which is this:
from __future__ import print_function
import sublime
import sublime_plugin
import os, os.path
from subprocess import call
# convert the current XML to binary via
# the converter -> who does actual work
class convert2libpart(sublime_plugin.WindowCommand):
def run(self, cmd="", file_regex="", path=""):
view = self.window.active_view()
self.plat = sublime.platform()
# get the settings
s = sublime.load_settings("somesettings.sublime-settings")
version = s.get("version") # this is from a settingsfile, as you can see
version = str(version)
if self.plat == "windows":
converter_path = "C:\\Program Files\\folder " + version + "\\"
#else:
# osx path... (program is available on both systems)
file_name = os.path.basename(view.file_name())
dir_path = os.path.dirname(view.file_name())
# XMLConverter xml2libpart source dest
cmd = "XMLConverter.exe xml2libpart " + "\"" + dir_path + "\\" + file_name + "\"" + " " + "\"" + dir_path + "output" + "\""
proc = call("start cmd /K " + cmd, cwd=converter_path, shell=True)
If I use this build system I can see in the task manager that the converter will start, but the output is not generated. Is it the program's fault?
Doing this manually with exact same command will produce the desired output.
Any thoughts? Thanks in advance.

python running lessc command

I have the following command
lessc lessc xyz.less > xyz.css
I want to run that command in python for which i have written this code
try:
project_path = settings.PROJECT_ROOT
less_path = os.path.join(project_path, "static\\less")
css_path = os.path.join(project_path, "static\\css")
except Exception as e:
print traceback.format_exc()
less_file = [f for f in os.listdir(less_path) if isfile(join(less_path, f))]
for files in less_file:
file_name = os.path.splitext(files)[0]
cmd = '%s\%s > %s\%s' % (less_path, files, css_path, file_name + '.css')
p = subprocess.Popen(['lessc', cmd], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
but it gives error windowerror 2 cannot find the path specifies
Make sure that 'lessc' is in your path, you could try using the full path to lessc instead.
You don't need to use shell style redirection with Popen like this, check the subprocess.Popen docs
Here is an example of how to do it without shell redirection:
import subprocess
lessc_command = '/path/to/lessc'
less_file_path = '/path/to/input.less'
css_file_path = '/path/to/output.css'
with open(css_file_path, 'w') as css_file:
less_process = subprocess.Popen([lessc_command, less_file_path], stdout=css_file)
less_process.communicate()

Categories

Resources