I have made a program, and there is a function where it gets a text file called news_2014.txt from a ftp server. I currently have this code:
def getnews():
server = 'my ftp server ip'
ftp= ftplib.FTP(server)
username = 'news2'
password = ' '
ftp.login(username,password)
filename = 'ftp://my ftp server ip/news/news_2014.txt'
path = 'news'
ftp.cwd(path)
ftp.retrlines('RETR' + filename, open(filename, "w").open)
I wanna make so the program displays the lines using readlines onto a Tkinter label. But if I try calling the top function, it says:
IOError: [Errno 22] invalid mode ('w') or filename: 'ftp://news/news_2014.txt'
RETR wants just the remote path name, not a URL. Similarly, you cannot open a URL; you need to pass it a valid local filename.
Changing it to filename = 'news_2014.txt' should fix this problem trivially.
The retrlines method retrieves the lines and optionally performs a callback. You have specified a callback to open a local file for writing, but that's hardly something you want to do for each retrieved line. Try this instead:
textlines = []
ftp.retrlines('RETR ' + filename, textlines.append)
then display the contents of textlines. (Notice the space between the RETR command and its argument, too.)
I would argue that the example in the documentation is confusing for a newcomer. Someone should file a bug report.
Related
I have this weird issue with my code on Raspberry Pi 4.
from gpiozero import CPUTemperature
from datetime import datetime
import ftplib
cpu = CPUTemperature()
now = datetime.now()
time = now.strftime('%H:%M:%S')
# Save data to file
f = open('/home/pi/temp/temp.txt', 'a+')
f.write(str(time) + ' - Temperature is: ' + str(cpu.temperature) + ' C\n')
# Login and store file to FTP server
ftp = ftplib.FTP('10.0.0.2', 'username', 'pass')
ftp.cwd('AiDisk_a1/usb/temperature_logs')
ftp.storbinary('STOR temp.txt', f)
# Close file and connection
ftp.close()
f.close()
When I have this code, script doesn't write anything to the .txt file and file that is transferred to FTP server has size of 0 bytes.
When I remove this part of code, script is writing to the file just fine.
# Login and store file to FTP server
ftp = ftplib.FTP('10.0.0.2', 'username', 'pass')
ftp.cwd('AiDisk_a1/usb/temperature_logs')
ftp.storbinary('STOR temp.txt', f)
...
ftp.close()
I also tried to write some random text to the file and run the script, and the file transferred normally.
Do you have any idea, what am I missing?
After you write the file, the file pointer is at the end. So if you pass file handle to FTP, it reads nothing. Hence nothing is uploaded.
I do not have a direct explanation for the fact the local file ends up empty. But the strange way of combining "append" mode and reading may be the reason. I do not even see a+ mode defined in open function documentation.
If you want to both append data to a local file and FTP, I suggest your either:
Append the data to the file – Seek back to the original position – And upload the appended file contents.
Write the data to memory and then separately 1) dump the in-memory data to a file and 2) upload it.
Have a peculiar issue that I can't seem to fix on my own..
I'm attempting to FTP a list of files in a directory over to an iSeries IFS using Python's ftplib library.
Note, the files are in a single subdirectory down from the python script.
Below is an excerpt of the code that is giving me trouble:
from ftplib import FTP
import os
localpath = os.getcwd() + '/Files/'
def putFiles():
hostname = 'host.name.com'
username = 'myuser'
password = 'mypassword'
myftp = FTP(hostname)
myftp.login(username, password)
myftp.cwd('/STUFF/HERE/')
for file in os.listdir(localpath):
if file.endswith('.csv'):
try:
file = localpath + file
print 'Attempting to move ' + file
myftp.storbinary("STOR " + file, open(file, 'rb'))
except Exception as e:
print(e)
The specific error that I am getting throw is:
Attempting to move /home/doug/Files/FILE.csv
426-Unable to open or create file /home/doug/Files to receive data.
426 Data transfer ended.
What I've done so far to troubleshoot:
Initially I thought this was a permissions issue on the directory containing my files. I used chmod 777 /home/doug/Files and re-ran my script, but the same exception occured.
Next I assumed there was an issue between my machine and the iSeries. I validated that I could indeed put files by using ftp. I was successfully able to put the file on the iSeries IFS using the shell FTP.
Thanks!
Solution
from ftplib import FTP
import os
localpath = os.getcwd() + '/Files/'
def putFiles():
hostname = 'host.name.com'
username = 'myuser'
password = 'mypassword'
myftp = FTP(hostname)
myftp.login(username, password)
myftp.cwd('/STUFF/HERE/')
for csv in os.listdir(localpath):
if csv.endswith('.csv'):
try:
myftp.storbinary("STOR " + csv, open(localpath + csv, 'rb'))
except Exception as e:
print(e)
As written, your code is trying to execute the following FTP command:
STOR /home/doug/Files/FILE.csv
Meaning it is trying to create /home/doug/Files/FILE.csv on the IFS. Is this what you want? I suspect that it isn't, given that you bothered to change the remote directory to /STUFF/HERE/.
If you are trying to issue the command
STOR FILE.csv
then you have to be careful how you deal with the Python variable that you've named file. In general, it's not recommended that you reassign a variable that is the target of a for loop, precisely because this type of confusion can occur. Choose a different variable name for localpath + file, and use that in your open(..., 'rb').
Incidentally, it looks like you're using Python 2, since there is a bare print statement with no parentheses. I'm sure you're aware that Python 3 is recommended by now, but if you do stick to Python 2, it's recommended that you avoid using file as a variable name, because it actually means something in Python 2 (it's the name of a type; specifically, the return type of the open function).
I'm really confused, I'm sure I'm missing something simple, but I can't understand why setting proxy environment variables works for some functions but not others. Is it that the libraries respond to these variables differently?
For example, I'm round-tripping a file via ftp. When I download with wget, I set the proxy environment variables and it downloads, but then say I want to put it back using ftplib, it gets [Errno 11001], do I need to specifically pass these proxy details through ftplib?
Say I set it up this way, I can download the file just fine:
# setup proxy
os.environ["ftp_proxy"] =
"http://****:****#proxyfarm.****.com:8080"
os.environ["http_proxy"] =
"http://****:****#proxyfarm.****.com:8080"
os.environ["https_proxy"] =
"http://****:****#proxyfarm.****.com:8080"
src = "ftp://****:****#ftp.blackrock.com/****/****.csv"
out = "C:\\outFolder\\outFileName.txt" # out is optional
# create output folder if it doesn't exists
outFolder, _ = os.path.split( out )
try:
os.makedirs(outFolder)
except OSError as exc: # Python >2.5
if exc.errno == errno.EEXIST and os.path.isdir(outFolder):
pass
else: raise
# download
filename = wget.download(src, out)
Now immediately below that, I switch to ftplib, I get the [Errno 11001], do I need to reset the proxy parameters for ftplib specifically?
session = ftplib.FTP('ftp.blackrock.com','****','****')
file = open(filename,'rb') # file to send
session.storbinary('STOR '+ remotePath + filename, file) # send the file
file.close() # close file and FTP
session.quit()
The ftp_proxy (and the others) is a proprietary feature of the wget.
You cannot expect it to work with any other FTP library/software.
I have written one function which recieves a url and copy it to all server.
Server remote path is stored in db.
def copy_image_to_server(image_url):
server_list = ServerData.objects.values_list('remote_path', flat=True).filter(active=1)
file = cStringIO.StringIO(urllib.urlopen(image_url).read())
image_file = Image.open(file)
image_file.seek(0)
for remote_path in server_list:
os.system("scp -i ~/.ssh/haptik %s %s " % (image_file, remote_path))
I am geeting this error at last line cannot open PIL.JpegImagePlugin.JpegImageFile: No such file
Please suggest me what's wrong in the code, i have checked url is not broken
The problem is that image_file is not a path (string), it's an object. Your os.system call is building up a string that expects a path.
You need to write the file to disk (perhaps using the tempfile module) before you can pass it to scp in this manner.
In fact, there's no need for you (at least in what you're doing in the code snippet) to convert it to a PIL Image object at all, you can just write it to disk once you've retrieved it, and then pass it to scp to move it:
file = cStringIO.StringIO(urllib.urlopen(image_url).read())
diskfile = tempfile.NamedTemporaryFile(delete=False)
diskfile.write(file.getvalue())
path = diskfile.name
diskfile.close()
for remote_path in server_list:
os.system("scp -i ~/.ssh/haptik %s %s " % (path, remote_path))
You should delete the file after you're done using it.
I don't know what I'm doing wrong but this small ftp code won't transfer files. I keep getting
File "example.py", line 11, in ?
ftp.storlines("STOR " + file, open(file))
ftplib.error_perm: 550 /home/helen/docs/example.txt: Operation not permitted
Here is the code:
import ftplib
file = '/home/helen/docs/example.txt'
ftp = ftplib.FTP('domain', 'user', 'password')
print "File List: "
files = ftp.dir()
ftp.cwd("/upload/")
ftp.storlines("STOR " + file, open(file))
f.close()
s.quit()
Any help would be appreciated.
I think the error you're getting is that you're adding the entire file path to the first argument in thestorlines()call. Instead, just specify the file name itself:
import os
ftp.storlines("STOR " + os.path.basename(file), open(file))
You might want to consider changingfiletofilepath,since that's what it really is (plus you will no longer be hiding the built-in function & type of the same name).
550 error literally means according to wikipedia "550 Requested action not taken. File unavailable (e.g., file not found, no access)."
http://en.wikipedia.org/wiki/List_of_FTP_server_return_codes
are you sure you have the right permissions?
try this
ftp = ftplib.FTP('domain')
ftp.login('user','pass')
i think the object creation was just a little jacked up.