Python 3 long filename as argument (python splits it) - python

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.

Related

Python's subprocess.check_output( )

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.

Python: Adding Variable paths into os.system("open"+filename)

I'm trying to make a script where python goes through a directory, finds all files that ends with *ref.SDAT, and then opens them all.
So far, I have the sorting of files process. The wanted files are put into reflist:
import os
import glob
import subprocess
os.chdir("/Users/BabyJ/Desktop/MRSDATA")
reflist = glob.glob('*raw_ref.SDAT')
print "These are the ref files:"
for i in reflist:
os.system('open+%s') %i
I don't know how to structure the syntax so that os.system will open all of the components of the list though.
The % operator wants the 'open+%s' string as its left-hand side. You are offering it the return value of os.system(). Also, I think you wanted a space, not a + in the string.
Try this:
os.system('open %s'%i)
I assuming judging from your use of open that you are on a Mac or Unix system. If that is the case use either of the following to get you up and running.
for i in reflist:
os.system('open ' + '%s' % i)
or:
for i in reflist:
subprocess.call('open ' + '%s' % i, shell = True)
Using subprocess is the better solution as os.system is, though not technically gone from the language, deprecated in Python per the official documentation.
Hope that helps.
EDIT:
If you're using windows sub in start for open.

7z will not find archive using subprocess

Struggling with this for literally two weeks. I can't get this .zip to unpack. I know that it is correct because I can make it work in a standard command line and it in shows everything that I know is in it. Trying to unpack a zip and then rename and copy portions of that file to another folder. Here is the basic setup:
import subprocess
cmd = ['7z', 'e', 'site']
sp = subprocess.Popen(cmd, stderr=subprocess.STDOUT, stdout=subprocess.PIPE)
After that import I try and unpack it using:
sp.communicate([cmd, 'r"C:\Users\boster\desktop\data1.zip"'])
now it gets past this point because it moves onto my if else section but it doesn't unpack it. I know that it will run the following because it gets to the end and returns my else statement and then prompts me to run the data again.
if "sz + business_date" == name:
shutil.copy(sz%s) % business_date
os.renames(sales.xls)
shutil.copy(sc%s) % business_date
os.renames(cosales.xls)
shutil.copy(aj%s) % business_date
os.renames(money.xls)
shutil.copy(cc%s) % business_date
os.renames(count.xls)
else:
print "Repoll %s for %s" % (item, business_date)
print "Once information is downloaded press enter."
re_download = raw_input(" ")
data_one()
I've left out some of the stuff like the business_date portions because it's returning that as a variable in the else so I know it's grabbing that information correctly. I just have no idea why this won't unpack. Please help. If this isn't sufficient I'll upload the whole module if you'd like.
I finally managed to get this to work. It wasn't unpacking on the subprocess.communicate and since call can't be used with PIPE I just dumped all the commands at the beggining and ended up with the following.
def extract_data_one():
for item in sites:
os.chdir(r"\\svr-dc\ftp site\%s\Daily" % item)
subprocess.call(['7z', 'e', 'data1.zip', '*.*'])
Thanks for all your help.
I encountered a similar problem when using 7zip compressed file with subprocess, I solved my problem by another way. This is my code,
def zip_files_in_special_path(rom_path, rom_name):
pre_cwd = os.getcwd()
os.chdir(rom_path)
cmd_str = r'C:\7-Zip\7z a -tzip -r '+rom_name+' *'
try:
status = os.system(cmd_str)
if status<=1:
return True
else:
raise RunCmdError('run 7z to zip files failed!')
finally:
os.chdir(pre_cwd)
hope to help you.

Python 2.6 on CentOs issues after install

I've been teaching myself python recently an came across and example where str.endswith took a tuple as it's first argument, which 2.4 doesn't support. I decided to try and install a newer version of Python on my machine so I was more up to date. The machine is CentOs5.
As my user on the machine (not root) I pulled the package from here: http://www.python.org/ftp/python/2.6.7/, uncompressed it, did ./configure --prefix=/home/myusername/python/compiler/Python-2.6.7-installed, then ran make, make test (all okay) and then finally make altinstall for good measure (I know it shouldn't be necessary to do altinstall as I specified a prefix but really don't want to break regular python on this machine). When it first didn't work I tried the make altinstall as root also, but it made no difference.
When I try to run a script against the binary I just get a bunch of gibberish like this:
./compiler/Python-2.6.7/Lib/test/test_re.pyc : onXtd}|iti|iddddgdS(Nsu" [\u002E\u3002\uFF0E\uFF61]"sa.b.cR$RHRX(R0RÑRÚR RRY(R R7((s#/home/yspendiff/python/compiler/Python-2.6.7/Lib/test/test_re.pyttest_bug_931848as
Cstidd}|i|iid|it|itidd}|i|i id|i|i ddS(Ns\ssa bii(ii(ii(
StopIterationRºRR(R RRÓR tnextRR4t
Rº((s#/home/yspendiff/python/compiler/Python- 2.6.7/Lib/test/test_re.pyttest_bug_581080js
cCsatidd}|i|iid|i|iid|it|idS(Ns.*tasdfii(ii(ii(RRÓR RÝRR4RÞ(R
and perhaps more pertinently lots of lines like these:
./compiler/Python-2.6.7/Lib/test/test_unicode.py : self.assert_(u'asdf' not in '')
./compiler/Python-2.6.7/Lib/test/test_unicode.py : self.assert_('asdf' not in u'')
./compiler/Python-2.6.7/Lib/test/test_unicode.py : self.assert_(u'asdf' not in u'')
./compiler/Python-2.6.7/Lib/test/test_re.py : iter = re.finditer(r".*", "asdf")
./compiler/Python-2.6.7/Lib/test/string_tests.py : self.checkequal(True, 'asdf', '__contains__', 'asdf')
./compiler/Python-2.6.7-installed/lib/python2.6/test/test_unittest.py : loader.loadTestsFromNames(['sdasfasfasdf'])
./compiler/Python-2.6.7-installed/lib/python2.6/test/test_unittest.py : self.assertEqual(str(e), "No module named sdasfasfasdf")
That is just a few random lines out of hundreds. I haven't messed around with any of the default options, have I pulled down a funny version or specified some funny compilation options. How do I turn it off so I can just code in peace!
The code is below if anyone is interested. I just call it with ./Findword.py asdf :
#!/home/myusername/python/compiler/Python-2.6.7-installed/bin/python2.6
### FindWord.py
import os # for curdir() #(A)
import os.path # for join(), isfile() #(B)
import sys # for argv[], exit() #(C)
if len( sys.argv ) != 2: #(D)
print "need a word or a single-quoted phrase to search for" #(E)
sys.exit(1) #(F)
def searchInFile( pattern, dirname, filenames ): #(G)
for name in filenames: #(H)
name = os.path.join( dirname, name ) #(I)
if os.path.isfile( name ) and not name.endswith(('.pdf','.pl')): #(J)
FH = open( name, 'r' ) #(K)
for eachline in FH: #(L)
if ( eachline.find( pattern ) != -1 ): #(M)
print name, ': ', eachline #(N)
os.path.walk( os.curdir, searchInFile, sys.argv[1] ) #(O)
Pretty much exactly what you're asking Python to do is happening. You're telling it to find the word 'asdf' from whatever your current directory is, it's finding it in binary files.

Learning python and having trouble with 1st program

I wrote this code and it is failing at line 11 on the "target_dir" command with invalid syntax I have a vm ubuntu and I just copy and pasted the code and it worked there but not in my win7 and I am not sure why. I was reading another question with similar code but it had a different error and noticed that someone said that some of these commands where obsolete so I was just wondering if that is so and I would just drop this book and move on to another one i just got.
Thanks in advance for the help,
# Filename: backup_ver1.py
import os
import time
# 1. The files and directories to be backed up are specified in a list.
source = ['"D:\\Warlock"', 'C:\\Druid'
# Notice we had to use double quotes inside the string for names with spaces in it.
# 2. The backup must be stored in a main backup directory
target_dir = r'C:\Backup' # Remember to change this to what you will be using
# 3. The files are backed up into zip file.
# 4. The name of the zip archive is the current date and time
target = target_dir + os.sep + time.strftime('%Y%m%d%H%M%S') + '.zip'
# 5. We use the zip commnad to put the files in a zip archive
zip_commnad = "7z a -tzip {0} {1}" .format(target, ' '.join(source))
print(zip_command)
#Run the backup
if os.system(zip_command) == 0:
print('Successful backup', target)
else:
print('Backup FAILED')
source = ['"D:\\Warlock"', 'C:\\Druid' is missing an end bracket. Should be source = ['"D:\\Warlock"', 'C:\\Druid'].
Edit: Also,
zip_commnad = "7z a -tzip {0} {1}" .format(target, ' '.join(source))
print(zip_command)
should be
zip_command = "7z a -tzip {0} {1}" .format(target, ' '.join(source))
print(zip_command)
i.e., spell command correctly and fix the indentation. Additionally, although defining the backup paths like you are is not an error, I'd agree with abaumg's comment that using raw strings would be a lot clearer.
In Python, an invalid syntax error often means that there is a syntax error, one or more lines above the line number that is reported.
Use an editor that does parenthesis hightlighting so that you can move your cursor along the line and see where there are missing or too many parentheses, braces, brackets, etc.
Also, you might want to have a look at the os.path module and get rid of the C: and the \ from your filenames. It is possible to make Python code portable between Linux and Windows. The drivenames could come from options (sys.argv) or a config file (ConfigParser) and the \ can be replaced by a single / and then you can use os.path.normcase() to normalize it for the current OS.

Categories