Python - reference a file in a different directory - python

I have to reference a file that exists in a different directory. This is just a text file, not a python module. I've read countless posts, most of which are about including modules. Nothing that I read is giving me a successful answer. Out of many attempts, this is my latest:
import os
REMOTE_FILE = open(os.path.join('/Users/me/Dropbox/otherfolder', 'text.txt'), "r")
decrypted = subprocess.check_output(['openssl', 'aes-128-cbc', '-d', '-in', REMOTE_FILE, '-base64', '-pass', key])
The program doesn't fail on this line immediately, but when I attempt to reference this file I get:
TypeError: Can't convert '_io.TextIOWrapper' object to str implicitly
What am I doing wrong? Thanks!

Use REMOTE_FILE = os.path.join('/Users/me/Dropbox/otherfolder', 'text.txt') instead to get only the file path as a string and not an file object.

Your REMOTE_FILE is a file object, not a string. Given your code, you probably meant to do:
import os
REMOTE_FILE = os.path.join('/Users/me/Dropbox/otherfolder', 'text.txt')
decrypted = subprocess.check_output(['openssl', 'aes-128-cbc', '-d', '-in', REMOTE_FILE, '-base64', '-pass', key])
Keeping REMOTE_FILE as a string, not an object.

Related

How do I write the time from datetime to a file in Python?

I'm trying to have my Python code write everything it does to a log, with a timestamp. But it doesn't seem to work.
this is my current code:
filePath= Path('.')
time=datetime.datetime.now()
bot_log = ["","Set up the file path thingy"]
with open ('bot.log', 'a') as f:
f.write('\n'.join(bot_log)%
datetime.datetime.now().strftime("%d-%b-%Y (%H:%M:%S.%f)"))
print(bot_log[0])
but when I run it it says:
Traceback (most recent call last):
File "c:\Users\Name\Yuna-Discord-Bot\Yuna Discord Bot.py", line 15, in <module>
f.write('\n'.join(bot_log)%
TypeError: not all arguments converted during string formatting
I have tried multiple things to fix it, and this is the latest one. is there something I'm doing wrong or missing? I also want the time to be in front of the log message, but I don't think it would do that (if it worked).
You need to put "%s" somewhere in the input string before string formatting. Here's more detailed explanation.
Try this:
filePath= Path('.')
time=datetime.datetime.now()
bot_log = "%s Set up the file path thingy\n"
with open ('bot.log', 'a') as f:
f.write(bot_log % datetime.datetime.now().strftime("%d-%b-%Y (%H:%M:%S.%f)"))
print(bot_log)
It looks like you want to write three strings to your file as separate lines. I've rearranged your code to create a single list to pass to writelines, which expects an iterable:
filePath= Path('.')
time=datetime.datetime.now()
bot_log = ["","Set up the file path thingy"]
with open ('bot.log', 'a') as f:
bot_log.append(datetime.datetime.now().strftime("%d-%b-%Y (%H:%M:%S.%f)"))
f.writelines('\n'.join(bot_log))
print(bot_log[0])
EDIT: From the comments the desire is to prepend the timestamp to the message and keep it on the same line. I've used f-strings as I prefer the clarity they provide:
import datetime
from pathlib import Path
filePath = Path('.')
with open('bot.log', 'a') as f:
time = datetime.datetime.now()
msg = "Set up the file path thingy"
f.write(f"""{time.strftime("%d-%b-%Y (%H:%M:%S.%f)")} {msg}\n""")
You could also look at the logging module which does a lot of this for you.

how to convert this Python code from sys.args to stdin

I used sys.arg instead of stdin but have no idea how to change it
My code creates error when reading the command line :
import sys
from pathlib import Path
import re
text_file = Path(sys.argv[1:])
if text_file.exists() and text_file.is_file():
read = text_file.read_text()
length = len(re.findall(r'[a-zA-Z]+', read))
print(f'{text_file} has', length, 'words')
else:
print(f'File not found: {text_file}')
This is the error that produces while running:
drv, root, parts = self._parse_args(args)
TypeError: expected str, bytes or os.PathLike object, not list
command line argument is - python3 total_words.py < lyrics/Justin_Bieber.txt (have the instructions to run the command line in this way)

TypeError: a bytes-like object is required, no 'str' when trying to write to a file

I'm trying to make an encrypted password manager. I've got almost everything done, except for saving the password along with the username and the site where I use it. When I execute the function that writes it to a file I get:
TypeError: a bytes-like object is required, not 'str'
The code is this and I'm using cryptography to encrypt the passwords:
from cryptography.fernet import Fernet
import errors
def write(text, key):
"""Encrypt and writes something to the passlist.encrypted file
Arguments:
text -- The list that will be written in the passlist.encrypted file
key -- The main key, generated from password"""
try:
if type(text) == list:
file = open('passlist.encrypted', 'wb')
for i in text:
message = i.encode()
f = Fernet(key)
encrypted = f.encrypt(message)
print(encrypted, file = file)
if i == text[-1]:
file.close()
else:
raise errors.invalidValueTypeError
except errors.invalidValueTypeError:
print('Error: Text must be a list')
Also, I'm trying to make that every string in the text list uses a different line and the previous text is not overwritten, but I can't make it work.
you've opened the file for writing with 'wb'– from the docs:
'b' appended to the mode opens the file in binary mode: now the data is read and written in the form of bytes objects. This mode should be used for all files that don’t contain text.
if you're writing a string to a file, open that file by doing open(filename, 'w')
As #David mentioned you can write the file with 'w' mode. Also, the code for writing the encrypted word in the file can be tweaked a bit to add new line
encrypted = f"{f.encrypt(message)}\n"

Check Size of File Assigned to a Variable in Python 2

I'm working on some code (that I have been given), as part of a coursework at University.
Part of the code requires that, we check the file we are writing to contains any data.
The file has been opened for writing within the code already:
f = open('newfile.txt', 'w')
Initially, I thought that I would just find the length of the file, however if I try: len(f)>512, I get an error:
TypeError: object of type 'file' has no len()
I have had a bit of a google and found various links, such as here, however when I try using the line: os.stat(f).st_size > 512, I get the following error message:
TypeError: coercing to Unicode: need string or buffer, file found
If I try and use the filename itself: os.stat("newfile.txt").st_size > 512, it works fine.
My question is, is there a way that I can use the variable that the file has been assigned to, f, or is this just not possible?
For context, the function looks like this:
def doData ():
global data, newblock, lastblock, f, port
if f.closed:
print "File " + f.name + " closed"
elif os.stat(f).st_size>512:
f.write(data)
lastblock = newblock
doAckLast()
EDIT: Thanks for the link to the other post Morgan, however this didn't work for me. The main thing is that the programs are still referencing the file by file path and name, whereas, I need to reference it by variable name instead.
According to effbot's Getting Information About a File page,
The os module also provides a fstat function, which can be used on an
opened file. It takes an integer file handle, not a file object, so
you have to use the fileno method on the file object:
This function returns the same values as a corresponding call to os.stat.
f = open("file.dat")
st = os.fstat(f.fileno())
if f.closed:
print "File " + f.name + " closed"
elif st.st_size>512:
f.write(data)
lastblock = newblock
doAckLast()

Decode content from httplib GET

I'm fetching a simple HTTP plain-text that is in CP-1250 (I can't influence that) and would like to decode it, process it per line and eventually save it as UTF-8.
The first part is causing me problems. After I get the raw data using response.read(), I'm passing it to a reader created by getreader("cp1250") from codecs library. I expect to get a StreamReader instance and simply call readlines to have a list of byte strings.
import codecs
import httplib
# nothing unusual
conn = httplib.HTTPConnection('server')
conn.request('GET', '/')
response = conn.getresponse()
content = response.read()
# the painful part
sr = codecs.getreader("cp1250")(content)
lines = sr.readlines() # d'oh!
But after the call to readlines I only get yells echoing from somewhere deep inside codecs:
[...snip...]
File "./download", line 123, in _parse
lines = sr.readlines()
File "/usr/lib/python2.7/codecs.py", line 588, in readlines
data = self.read()
File "/usr/lib/python2.7/codecs.py", line 471, in read
newdata = self.stream.read()
AttributeError: 'str' object has no attribute 'read'
My prints confirm that sr is instance of StreamReader; it confuses me that the object seemed to initialize well but now fails to execute the readlines ... what is missing here?
Or is the library trying to cryptically tell me that the data is corrupted (not CP-1250)?
Edit: As jorispilot suggests, unicode(content, encoding="cp1250") works, so I'll probably stick with that for my solution. However, I'd still like to know what was wrong with my usage of codecs library.
utf8_lines = []
for line in content.split('\n'):
line = line.strip().decode('cp1250')
utf8_lines.append(line.encode('utf-8'))
According to http://docs.python.org/2/library/codecs.html, getreader() returns a StreamReader. This must be passed a stream, which implements the read() function, not, as you are doing, a string.
To fix this, don't read the data from response, but pass it directly to the StreamReader, as below.
conn = httplib.HTTPConnection('server')
conn.request('GET', '/')
response = conn.getresponse()
reader = codecs.getreader("cp1250")(response)
lines = sr.readlines()

Categories

Resources