Python argparse opening multiple files - python-3.x

i'm trying to access multiple .txt files with argparse and i've stumbled across a problem which i can't put my head around.
parser = argparse.ArgumentParser()
parser.add_argument('filename', nargs='+'. type=argparse.FileType('r'))
args = parser.parse_args()
with open(args.filename, 'r') as files:
#do stuff to files
and i'm trying to access with
EDIT:
python3 script.py file1.txt file2.txt
But i'm getting an error as such:
Traceback (most recent call last):
File "script.py", line 34 in <module>
with open(args.filename, 'r') as files:
TypeError: expected str, bytes or os.PathLike objects, not list
I somewhat know what that means, but i just can't put my finger on what to do next.

From documentation nargs:
'+'. Just like '*', all command-line args present are gathered into a list. Additionally, an error message will be generated if there wasn’t at least one command-line argument present.
So, If you want to open multiple files, u have to iter through your list with args. For example:
parser = argparse.ArgumentParser()
parser.add_argument('filename', nargs='+')
args = parser.parse_args()
for file_name in args.filename:
with open(file_name, 'r') as files:
<do your code here>
# a = files.read()
# print(a)

Related

Iterating through directory error: FileNotFoundError: [Errno 2] No such file or directory

I wrote a script to iterate through multiple text files in a directory and count the words contained in each that are also contained in a dictionary file. I wrote and tested the script with two files in the directory, and got it working perfectly, the script spits out two accurate integers, one for each file. However, once I add new files to the directory, I get a FileNotFound error. The file is definitely in there! Can anyone tell me what it is about the code that is causing this? I've gone through various other such posts on StackOverflow with no success. The newly added file has all the same properties as the existing two.
Code (word_count_from_dictionary-iterating.py):
import os
import sys
import nltk
nltk.download()
from nltk import word_tokenize
from nltk.corpus import stopwords
from nltk.stem import WordNetLemmatizer
import io
files_path = sys.argv[1]
textfile_dictionary = sys.argv[2]
for filename in os.listdir(files_path):
if filename.endswith(".txt"):
#accessing file for processing
file = open(filename, "rt")
text = file.read()
#tokenize text file
tokens = word_tokenize(text)
#remove non-alphabetical characters
words = []
for word in tokens:
if word.isalpha():
words.append(word)
#remove stopwords
stop_words = stopwords.words("english")
words_without_stops = []
for w in words:
if not w in stop_words:
words_without_stops.append(w)
#lemmatize remaining tokens and print
lemmatizer = WordNetLemmatizer()
lemmas = []
for x in words_without_stops:
lemmatizer.lemmatize(x)
lemmas.append(x)
#turn dictionary held in text file into a list of tokens
file = io.open(textfile_dictionary, mode="r", encoding="utf8")
dictionaryread = file.read()
dictionary = dictionaryread.split()
#count instances of each word in dictionary in the novel and add them up
word_count = 0
for element in dictionary:
for lemma in lemmas:
if lemma == element:
word_count = word_count + 1
print(word_count)
Results on command line with just two test files in the directory:
c#Computer:~/Dropbox/programming/first_project$ python3 word_count_from_dictionary_iterating.py directoryaddress dictionary.txt
showing info https://raw.githubusercontent.com/nltk/nltk_data/gh-pages/index.xml
241
229
Results after adding a new file (newfile.txt) to the directory:
c#Computer:~/Dropbox/programming/first_project$ python3 word_count_from_dictionary_iterating.py directoryaddress happy_words.txt
showing info https://raw.githubusercontent.com/nltk/nltk_data/gh-pages/index.xml
241
229
Traceback (most recent call last):
File "word_count_from_dictionary_iterating.py", line 17, in <module>
file = open(filename, "rt")
FileNotFoundError: [Errno 2] No such file or directory: 'newfile.txt'
If I run ls on the directory, the file is showing up. If I apply the script, adjusted without the iterating loop, to newfile.txt, it works. But it's just not working when looping through the directory.
Any help appreciate, I am new to programming.
The issue is when you run file = open(filename, "rt"), it is looking for filename in the directory where you started Python (~/Dropbox/programming/first_project/), but you want it to read ~/Dropbox/programming/first_project/directoryaddress.
To ensure you reading the right file, you should either pass in the full path of it as filename or, if you know you will always find it in some subdirectory, simply prepend the path to filename before trying to read it file = open(files_path+"/"+filename, "rt") (there are cleaner ways to combine paths, like the standard library pathlib).

How to randomly copy the contents of a text document to my clipboard

This is my original question
The following script copies the text in /home/my_files/document1.txt to my clipboard.
import pyperclip
path = '/home/my_files/document1.txt'
The_text_of_the_file_that_will_be_copied = open(path, 'r').read()
pyperclip.copy(The_text_of_the_file_that_will_be_copied)
Let's say /home/my_files/ contains the following five documents:
/home/my_files/document1.txt
/home/my_files/document2.txt
/home/my_files/document3.txt
/home/my_files/image1.jpg
/home/my_files/image2.png
I would like to create a script to randomly copy the contents of one of the three text documents in /home/my_files/ to my clipboard.
Of course the following script does not work but it shows some of the modules I've been experimenting with.
import glob,random,pyperclip
pattern = "*.txt"
path = random.choice((glob.glob(pattern))("/home/my_files/"))
The_text_of_the_file_that_will_be_copied = open(path, 'r').read()
pyperclip.copy(The_text_of_the_file_that_will_be_copied)
Do you have any relevant suggestions for me?
I added the subsequent content to my original question above
When I tried the following solution which #Jacob Lee created...
import glob
import random
import pyperclip
files = [os.path.abspath(f) for f in glob.glob("./home/my_files")]
path = random.choice(files)
with open(path) as f:
pyperclip.copy(f.read())
I received the following error message...
Traceback (most recent call last):
File "abc.py", line 3, in <module>
path = random.choice(glob.glob(pattern))
File "/usr/lib/python3.8/random.py", line 290, in choice
raise IndexError('Cannot choose from an empty sequence') from None
IndexError: Cannot choose from an empty sequence
Someone else suggested the following script to me...
import glob,random,pyperclip
pattern = "/home/my_files/*.txt"
path = random.choice(glob.glob(pattern))
print("copying contents of ", path)
The_text_of_the_file_that_will_be_copied = open(path, 'r').read()
pyperclip.copy(The_text_of_the_file_that_will_be_copied)
But that script doesn't work either. I received the following error when I ran that script...
Traceback (most recent call last):
File "abc.py", line 3, in <module>
path = random.choice(glob.glob(pattern))
File "/usr/lib/python3.8/random.py", line 290, in choice
raise IndexError('Cannot choose from an empty sequence') from None
IndexError: Cannot choose from an empty sequence
I am confused.
The following successfully copies the entire contents of a random text file in /home/my_files/ to my clipboard
import glob,random,pyperclip
pattern = "/home/my_files/*.txt"
path = random.choice(glob.glob(pattern))
print("copying contents of ", path)
The_text_of_the_file_that_will_be_copied = open(path, 'r').read()
pyperclip.copy(The_text_of_the_file_that_will_be_copied)
Thanks to #Asocia
Thanks to #Asocia for insisting that the script above works correctly. I don't know what I had been doing wrong, but I must have been doing something wrong when I indicated the script above did not work properly.
You're code raises a TypeError: 'list' object is not callable exception when you try to assign path, in this line:
path = random.choice((glob.glob(pattern))("/home/my_files"))
glob.glob() returns a list (possibly empty). (Also, you put the glob.glob() call inside redundant parentheses.) Then, you try to call glob.glob()("/home/my_files/") (in essence, [...](), raising the TypeError exception.
import glob
import random
import pyperclip
files = [os.path.abspath(f) for f in glob.glob("./home/my_files/*.txt")]
path = random.choice(files)
with open(path) as f:
pyperclip.copy(f.read())

Error when trying to create a file in a path containing parentheses with Python

Can anyone spot why this is failing?
import pathlib
from shlex import quote
path = 'testdir(abc)/subdir(123)'
filename = 'test'
content = \
"""hello
world
"""
pathlib.Path(path).mkdir(mode=0o770, parents=True, exist_ok=True)
md5_filename = quote(str(pathlib.Path(path) / (filename + '.txt')))
with open(md5_filename, 'w') as f:
f.write(content)
I'm getting this traceback
(tools) $ python test_filemake.py
Traceback (most recent call last):
File "test_filemake.py", line 13, in <module>
with open(md5_filename, 'w') as f:
FileNotFoundError: [Errno 2] No such file or directory: "'testdir(abc)/subdir(123)/test.txt'"
I think I don't understand posix paths well enough to understand what's going on. If I take the parentheses out of the directory names in the path, it works fine. shlex.quote() is adding the extra layer of double quotes, which seems to be breaking things.

Python: copy file tree to a text file

I'm trying to create a text file with a tree of all files / dirs from a place that I choose using os.chdir(). My approach is to print the tree and to save all prints to the text file. The problem is that it doesn't copy the printed tree and the file is blank.
What am I doing wrong?
And is there a way to write this kind of data to the file without to actually print it?
My code:
import os
import sys
f = open("tree.txt", "w")
os.chdir("c:\\Users\Daniel\Desktop")
sys.stdout = f
os.system("tree /f")
f.close()
Edit
I was able to get the file tree from the clipboard after executing the command, however it gives me and eror when it tried to write to the txt file.
code:
import os
import tkinter
with open("tree.txt", "w") as f:
os.system("tree /f |clip")
root = tkinter.Tk()
tree = root.clipboard_get()
print(tree)
f.write(tree)
eror:
Traceback (most recent call last):
File "c:\Users\Daniel\Desktop\Tick\code_test\files.py", line 9, in <module>
f.write(tree)
File "C:\Users\Daniel\AppData\Local\Programs\Python\Python38-32\lib\encodings\cp1252.py", line 19, in encode
return codecs.charmap_encode(input,self.errors,encoding_table)[0]
UnicodeEncodeError: 'charmap' codec can't encode character '\u2502' in position 80: character maps to <undefined>
solution
So I found the problem, I needed to use codec to be able write unicode to the text file. Now it works very well
code:
import os
import tkinter
import codecs
with codecs.open("tree.txt", "w", "utf8") as f:
os.chdir("c:\\Users")
os.system("tree /f |clip")
root = tkinter.Tk()
tree = root.clipboard_get()
f.write(tree)
Method check_output from subprocess module can help you to catch program output:
import subprocess
f = open("tree.txt", "wb")
tree_output = subprocess.check_output('tree /f', shell=True, cwd=r'c:\Users\Daniel\Desktop')
f.write(tree_output)
f.close()
Or with context manager:
import subprocess
with open("tree.txt", "wb") as f:
f.write(subprocess.check_output('tree /f', shell=True, cwd=r'c:\Users\Daniel\Desktop'))
Option wb is required because check_output returns bytes not a str. If you want to process output like a string - call tree_output.decode() first.

Writing pdf with pypdf2 gives error

I'm trying to write a simple script to merge two PDFs but have run into an issue when trying to save the output to disk. My code is
from PyPDF2 import PdfFileWriter, PdfFileReader
import tkinter as tk
from tkinter import filedialog
### Prompt the user for the 2 files to use via GUI ###
root = tk.Tk()
root.update()
file_path1 = tk.filedialog.askopenfilename(
filetypes=[("PDF files", "*.pdf")],
)
file_path2 = tk.filedialog.askopenfilename(
filetypes=[("PDF files", "*.pdf")],
)
###Function to combine PDFs###
output = PdfFileWriter()
def append_pdf_2_output(file_handler):
for page in range(file_handler.numPages):
output.addPage(file_handler.getPage(page))
#Actually combine the 2 PDFs###
append_pdf_2_output(PdfFileReader(open(file_path1, "rb")))
append_pdf_2_output(PdfFileReader(open(file_path2, "rb")))
###Prompt the user for the file save###
output_name = tk.filedialog.asksaveasfile(
defaultextension='pdf')
###Write the output to disk###
output.write(output_name)
output.close
The problem is that I get an error of
UserWarning: File to write to is not in binary mode. It may not be written to correctly. [pdf.py:453] Traceback (most recent call last): File "Combine2Pdfs.py", line 44, in output.write(output_name) File "/Library/Frameworks/Python.framework/Versions/3.5/lib/pytho‌​n3.5/site-packages/P‌​yPDF2/pdf.py", line 487, in write stream.write(self.header + b("\n")) TypeError: write() argument must be str, not bytes
Where have I gone wrong?
I got it by adding mode = 'wb' to tk.filedialog.asksaveasfile. Now it's
output_name = tk.filedialog.asksaveasfile(
mode = 'wb',
defaultextension='pdf')
output.write(output_name)
Try to use tk.filedialog.asksaveasfilename instead of tk.filedialog.asksaveasfile. You just want the filename, not the file handler itself.
###Prompt the user for the file save###
output_name = tk.filedialog.asksaveasfilename(defaultextension='pdf')

Resources