I am running 32-bit Windows 7 and Python 2.7.
I am trying to write a command line Python script that can run from CMD. I am trying to assign a value to sys.argv[1]. The aim of my script is to calculate the MD5 hash value of a file. This file will be inputted when the script is invoked in the command line and so, sys.argv[1] should represent the file to be hashed.
Here's my code below:
import sys
import hashlib
filename = sys.argv[1]
def md5Checksum(filePath):
fh = open(filePath, 'rb')
m = hashlib.md5()
while True:
data = fh.read(8192)
if not data:
break
m.update(data)
return m.hexdigest()
# print len(sys.argv)
print 'The MD5 checksum of text.txt is', md5Checksum(filename)
Whenver I run this script, I receive an error:
filename = sys.argv[1]
IndexError: list index out of range
To call my script, I have been writing "script.py test.txt" for example. Both the script and the source file are in the same directory. I have tested len(sys.argv) and it only comes back as containing one value, that being the python script name.
Any suggestions? I can only assume it is how I am invoking the code through CMD
You should check that in your registry the way you have associated the files is correct, for example:
[HKEY_CLASSES_ROOT\Applications\python.exe\shell\open\command]
#="\"C:\\Python27\\python.exe\" \"%1\" %*"
The problem is in the registry. Calling python script.py test.txt works, but this is not the solution. Specially if you decide to add the script to your PATH and want to use it inside other directories as well.
Open RegEdit and navigate to HKEY_CLASSES_ROOT\Applications\python.exe\shell\open\command. Right click on name (Default) and Modify. Enter:
"C:\Python27\python.exe" "%1" %*
Click OK, restart your CMD and try again.
try to run the script using python script.py test.txt, you might have a broken association of the interpreter with the .py extention.
Did you try sys.argv[0]? If len(sys.argv) = 0 then sys.argv[1] would try to access the second and nonexistent item
Related
I'm trying to write a cli that will take a users path that they input into the command line, then add this path to the correct path file depending on their shell - in this case zsh. I have tried using:
shell = str(subprocess.check_output("echo $SHELL", shell=True))
click.echo("Enter the path you would like to add:")
path = input()
if 'zsh' in shell:
with open(".zshrc", 'w') as zsh:
zsh.write(f'export PATH="$PATH:{path}"')
This throws no errors but doesn't seem to add to the actual ~./zshrc file.
Is there a better way to append to the file without manually opening the file and typing it in?
New to this so sorry if it's a stupid question...
Open the file in append mode. Your code also assumes that the current working directory is the user's home directory, which is not a good assumption to make.
from pathlib import Path
import os
if 'zsh' in os.environ.get("SHELL", ""):
with open(Path.home() / ".zshrc", 'a') as f:
f.write(f'export PATH={path}:$PATH')
with (Path.home() / ".zshrc').open("a") as f: would work as well.
Note that .zprofile would be the preferred location for updating an envirornent variable like PATH, rather than .zshrc.
Solved! Just want to put the answer here if anyone comes across the same problem.
Instead of trying to open the file with
with open(".zshrc", 'w') as zsh:
zsh.write(f'export PATH="$PATH:{path}"')
you can just do
subprocess.call(f"echo 'export PATH=$PATH:{path}' >> ~/.zshrc", shell=True)
If anybody has a way of removing from ~/.zshrc with python that would be very helpful...
I am working on Debian Stable Linux which is otherwise working very well. I have following code in a python script file named "myrev" which works to reverse order of lines of given text file:
#! /usr/bin/python3
import sys
if len(sys.argv) < 2:
print("Usage: myrev infile")
sys.exit()
try:
with open(sys.argv[1], "r") as f:
lines = f.read().split("\n")
except:
print("Unable to read infile.")
sys.exit()
lines.reverse()
print("\n".join(lines))
It works properly and prints out reverse order of lines if I use following Linux command
./myrev infile
However, if I try to redirect output with following command to original file, a blank file is generated:
./myrev infile > infile
After above command, infile becomes an empty file.
Why can't I redirect output to original file and how can this be solved?
Using > opens the target file for write, same as if opened via fopen with mode "w". That immediately truncates the file, before your program even launches (it happens while the shell is configuring the environment before execing your program). You can't use this approach to read from a file and replace it as a single step. Best you could do would be something like:
./myrev infile > infile.tmp && mv -f infile.tmp infile
where, if the command succeeds, you complete the work by replacing the original file with the contents of the new file.
I am converting some Python scripts I wrote in a Windows environment to run in Unix (Red Hat 5.4), and I'm having trouble converting the lines that deal with filepaths. In Windows, I usually read in all .txt files within a directory using something like:
pathtotxt = "C:\\Text Data\\EJC\\Philosophical Transactions 1665-1678\\*\\*.txt"
for file in glob.glob(pathtotxt):
It seems one can use the glob.glob() method in Unix as well, so I'm trying to implement this method to find all text files within a directory entitled "source" using the following code:
#!/usr/bin/env python
import commands
import sys
import glob
import os
testout = open('testoutput.txt', 'w')
numbers = [1,2,3]
for number in numbers:
testout.write(str(number + 1) + "\r\n")
testout.close
sourceout = open('sourceoutput.txt', 'w')
pathtosource = "/afs/crc.nd.edu/user/d/dduhaime/data/hill/source/*.txt"
for file in glob.glob(pathtosource):
with open(file, 'r') as openfile:
readfile = openfile.read()
souceout.write (str(readfile))
sourceout.close
When I run this code, the testout.txt file comes out as expected, but the sourceout.txt file is empty. I thought the problem might be solved if I change the line
pathtosource = "/afs/crc.nd.edu/user/d/dduhaime/data/hill/source/*.txt"
to
pathtosource = "/source/*.txt"
and then run the code from the /hill directory, but that didn't resolve my problem. Do others know how I might be able to read in the text files in the source directory? I would be grateful for any insights others can offer.
EDIT: In case it is relevant, the /afs/ tree of directories referenced above is located on a remote server that I'm ssh-ing into via Putty. I'm also using a test.job file to qsub the Python script above. (This is all to prepare myself to submit jobs on the SGE cluster system.) The test.job script looks like:
#!/bin/csh
#$ -M dduhaime#nd.edu
#$ -m abe
#$ -r y
#$ -o tmp.out
#$ -e tmp.err
module load python/2.7.3
echo "Start - `date`"
python tmp.py
echo "Finish - `date`"
Got it! I had misspelled the output command. I wrote
souceout.write (str(readfile))
instead of
sourceout.write (str(readfile))
What a dunce. I also added a newline bit to the line:
sourceout.write (str(readfile) + "\r\n")
and it works fine. I think it's time for a new IDE!
You haven't really closed the file. The function testout.close() isn't called, because you have forgotten the parentheses. The same is for sourceout.close()
testout.close
...
sourceout.close
Has to be:
testout.close()
...
sourceout.close()
If the program finishes all files are automatically closed so it is only important if you reopen the file.
Even better (the pythonic version) would be to use the with statement. Instead of this:
testout = open('testoutput.txt', 'w')
numbers = [1,2,3]
for number in numbers:
testout.write(str(number + 1) + "\r\n")
testout.close()
you would write this:
with open('testoutput.txt', 'w') as testout:
numbers = [1,2,3]
for number in numbers:
testout.write(str(number + 1) + "\r\n")
In this case the file will be automatically closed even when an error occurs.
I'm currently creating a script that will simply open a program in the SAME directory as the script. I want to have a text file named "target.txt", and basically the script will read what's in "target.txt" and open a file based on its contents.
For example.. The text file will read "program.exe" inside, and the script will read that and open program.exe. The reason I'm doing this is to easily change the program the script opens without having to actually change whats inside.
The current script Im using for this is:
import subprocess
def openclient():
with open("target.txt", "rb") as f:
subprocess.call(f.read())
print '''Your file is opening'''
Its giving me an error saying it cannot find target.txt, even though I have it in the same directory. I have tried taking away the .txt, still nothing. This code actually worked before, however; it stopped working for some strange reason. I'm using PythonWin compiler instead of IDLE, I don't know if this is the reason.
There are two possible issues:
target.txt probably ends with a newline, which messes up subprocess.call()
If target.txt is not in the current directory, you can access the directory containing the currently executing Python file by parsing the magic variable __file__.
However, __file__ is set at script load time, and if the current directory is changed between loading the script and calling openclient(), the value of __file__ may be relative to the old current directory. So you have to save __file__ as an absolute path when the script is first read in, then use it later to access files in the same directory as the script.
This code works for me, with target.txt containing the string date to run the Unix date command:
#!/usr/bin/env python2.7
import os
import subprocess
def openclient(orig__file__=os.path.abspath(__file__)):
target = os.path.join(os.path.dirname(orig__file__), 'target.txt')
with open(target, "rb") as f:
subprocess.call(f.read().strip())
print '''Your file is opening'''
if __name__ == '__main__':
os.chdir('foo')
openclient()
I am writing a script to clean up my desktop, moving files based on file type. The first step, it would seem, is to ls -1 /Users/user/Desktop (I'm on Mac OSX). So, using Python, how would I run a command, then write the output to a file in a specific directory? Since this will be undocumented, and I'll be the only user, I don't mind (prefer?) if it uses os.system().
You can redirect standard output to any file using > in command.
$ ls /Users/user/Desktop > out.txt
Using python,
os.system('ls /Users/user/Desktop > out.txt')
However, if you are using python then instead of using ls command you can use os.listdir to list all the files in the directory.
path = '/Users/user/Desktop'
files = os.listdir(path)
print files
After skimming the python documentation to run shell command and obtain the output you can use the subprocess module with the check_output method.
After that you can simple write that output to a file with the standard Python IO functions: File IO in python.
To open a file, you can use the f = open(/Path/To/File) command. The syntax is f = open('/Path/To/File', 'type') where 'type' is r for reading, w for writing, and a for appending. The commands to do this are f.read() and f.write('content_to_write'). To get the output from a command line command, you have to use popen and subprocess instead of os.system(). os.system() doesn't return a value. You can read more on popen here.