I'd like to be able to transfer files between my mobile phone and computer. The phone is a smartphone that can run python 2.5.4 and the computer is running windows xp (with python 2.5.4 and 3.1.1).
I'd like to have a simple python program on the phone that can send files to the computer and get files from the computer. The phone end should only run when invoked, the computer end can be a server, although preferably something that does not use a lot of resources. The phone end should be able to figure out what's in the relevant directory on the computer.
At the moment I'm getting files from computer to phone by running windows web server on the computer (ugh) and a script with socket.set_ default _ access_point (so the program can pick my router's ssid or other transport) and urlretrieve (to get the files) on the phone. I'm sending files the other way by email using smtplib.
Suggestions would be appreciated, whether a general idea, existing programs or anything in between.
I would use paramiko. It's secure fast and really simple. How bout this?
So we start by importing the module, and specifying the log file:
import paramiko
paramiko.util.log_to_file('/tmp/paramiko.log')
We open an SSH transport:
host = "example.com"
port = 22
transport = paramiko.Transport((host, port))
Next we want to authenticate. We can do this with a password:
password = "example101"
username = "warrior"
transport.connect(username = username, password = password)
Another way is to use an SSH key:
import os
privatekeyfile = os.path.expanduser('~/.ssh/id_rsa')
mykey = paramiko.RSAKey.from_private_key_file(privatekeyfile)
username = 'warrior'
transport.connect(username = username, pkey = mykey)
Now we can start the SFTP client:
sftp = paramiko.SFTPClient.from_transport(transport)
Now lets pull a file across from the remote to the local system:
filepath = '/home/zeth/lenna.jpg'
localpath = '/home/zeth/lenna.jpg'
sftp.get(filepath, localpath)
Now lets go the other way:
filepath = '/home/zeth/lenna.jpg'
localpath = '/home/zeth/lenna.jpg'
sftp.put(filepath, localpath)
Lastly, we need to close the SFTP connection and the transport:
sftp.close()
transport.close()
How's that?? I have to give credit to this for the example.
I ended up using python's ftplib on the phone and FileZilla, an ftp sever, on the computer. Advantages are high degree of simplicity, although there may be security issues.
In case anyone cares, here's the guts of the client side code to send and receive files. Actual implementation has a bit more infrastructure.
from ftplib import FTP
import os
ftp = FTP()
ftp.connect(server, port)
ftp.login(user, pwd)
files = ftp.nlst() # get a list of files on the server
# decide which file we want
fn = 'test.py' # filename on server and for local storage
d = 'c:/temp/' # local directory to store file
path = os.path.join(d,fn)
r = ftp.retrbinary('RETR %s' % fn, open(path, 'wb').write)
print(r) # should be: 226 Transfer OK
f = open(path, 'rb') # send file at path
r = ftp.storbinary('STOR %s' % fn, f) # call it fn on server
print(r) # should be: 226 Transfer OK
f.close()
ftp.quit()
There are a couple of examples out there, but you have to keep in mind that, IIRC, PyBluez will work only on Linux.
I've previously done OBEX-related things, mostly fetching things from
mobile phones, using the obexftp program 2 which is part of the
OpenOBEX project 3. Naturally, you can call the obexftp program from
Python and interpret the responses and exit codes using functions in
the os, popen2 and subprocess modules. I believe that obexftp also
supports "push" mode, but you could probably find something else
related to OpenOBEX if it does not.
Since Bluetooth communications are supported using sockets in GNU/
Linux distributions and in Python (provided that the Bluetooth support
is detected and configured), you could communicate with phones using
plain network programming, but this would probably require you to
implement the OBEX protocols yourself - not a straightforward task for
a number of reasons, including one I mention below. Thus, it's
probably easier to go with obexftp at least initially.
You also have lightblue, that is a cross-os bluetooth library.
There is also a complete script, PUTools: Python Utility Tools for PyS60 Python (examples has Windows screenshots), that has a:
Python interpreter that takes input and shows output on PC, connects over Bluetooth to phone, and executes on the phone. You also get simple shell functionality for the phone (cd, ls, rm, etc.). The tool also allows you to synchronize files both from PC to phone (very useful in application development) and from phone to PC (your images, logfiles from the program you are working on, etc.).
Related
I'm trying to download a file from a ftp server of a client. I have my code that gets the file and it works fine on my laptop. When I run it from the console in my production server which is inside a virtual machine it doesn't work. It also doesnt work on a virtual machine inside of my desktop pc.
The timout happen on ftp.retrbinary
Code:
# python > 3.6
from ftplib import FTP
file_csv = 'test.txt'
ftp = FTP(host=hostname, timeout=20)
login = ftp.login(user=user_name, passwd=user_pass)
ftp.set_pasv(False)
ftp.cwd('/csv_files/')
localfile = open(file_csv, 'wb')
ftp.retrbinary('RETR ' + file_csv, localfile.write, 1024)
ftp.quit()
localfile.close()
I've set the timeout to 20 or the code will never stop unless i force it. The message i get after the time out is
~/.pyenv/versions/3.6.8/lib/python3.6/socket.py in accept(self)
203 For IP sockets, the address info is a pair (hostaddr, port).
204 """
--> 205 fd, addr = self._accept()
206 # If our type has the SOCK_NONBLOCK flag, we shouldn't pass it onto the
207 # new socket. We do not currently allow passing SOCK_NONBLOCK to
I haven't been able to solve this. Please if someone can help with this, tahnks.
Do not use FTP active mode, unless you have a very specific reason to do so. The active mode usually does not work due to ubiquitous firewalls and NATs.
Use the passive mode instead. To use the passive mode, remove this call:
ftp.set_pasv(False)
ftplib defaults to the passive mode.
For some background, refer to my article on FTP connection modes.
Thanks for the answer Martin, I need to use set_pasv or it wont work.
I Solved the problem, my virtualmachine was using the default NAT settings. After switching to another settings it worked.(to 'Use bridged networking' on vmware)
I have this code that is supposed to connect to wifi using a given ESSID and password. Here is the code:
def wifi_connect(essid, password):
# Connect to the wifi. Based on the example in the micropython
# documentation.
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
if not wlan.isconnected():
print('connecting to network ' + essid + '...')
wlan.connect(essid, password)
# connect() appears to be async - waiting for it to complete
while not wlan.isconnected():
print('waiting for connection...')
print('checking connection...')
print('Wifi connect successful, network config: %s' % repr(wlan.ifconfig()))
else:
# Note that connection info is stored in non-volatile memory. If
# you are connected to the wrong network, do an explicity disconnect()
# and then reconnect.
print('Wifi already connected, network config: %s' % repr(wlan.ifconfig()))
At first, I got an error message that network was not installed. This was fixed by simply using pip to install network. After I ran this again, it told me that network has no attribute WLAN. How do I fix this? What am I doing wrong?
You are trying to run code designed for the MicroPython language, and it won't work on CPython (the Python version you'd download from Python.org or find installed on most PCs and servers).
MicroPython is designed to run on embeddable specialist hardware, and comes with its own library to support the hardware it is running on, including a network module:
To use this module, a MicroPython variant/build with network capabilities must be installed. Network drivers for specific hardware are available within this module and are used to configure hardware network interface(s).
It tells you so in the comments at the top:
# [...] Based on the example in the micropython
# documentation.
The code can't run on 'regular' CPython. You installed the PyPI network project, which is a very different module, originally designed to help learn coding for the Raspberry PI.
What project could work depends on your operating system (OS). Different OSes use different programming interfaces to let programs change networks. Most have command line tools to let you do this, which should be easy to drive from Python with the subprocess module:
Windows has the netsh command, run netsh wlan connect name=... to connect to a network interface
Mac OS X has the networksetup command, networksetup -setairportnetwork en1 ... connects you to a given WIFI network.
On a PC, you don't need network.py to connect to a Wifi access point as in ESPP32.
You connect normally by OS network connection.
The only library you need is socket. Here an example of code to get data !
import socket
def http_get(url, port):
_, _, host, path = url.split('/', 3)
addr = socket.getaddrinfo(host, port)[0][-1]
s = socket.socket()
s.connect(addr)
s.send(bytes('GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n' % (path, host), 'utf8'))
while True:
data = s.recv(100)
if data:
print(str(data, 'utf8'), end='')
else:
break
s.close()
http_get('http://micropython.org/ks/test.html',80)
http_get('http://towel.blinkenlights.nl/',23)
I have two linux computers with fixed IP addresses:
A print server, whereby the connected printer is shared via CUPS.
(The server has the IP address "192.168.1.2" and the printer is called "test_printer".)
A computer, on which a python application is running, that should be able to use this print server.
Unfortunately, the printer propagation via CUPS seems not to work reliably (possibly due to the structure of the network).
Can I send print jobs directly from a python program to the CUPS print server?
If so, can you please provide a small example?
In theory, I would just send correctly formatted data to the IP address + port, but I didn't get it to work ...
Here are the approaches I have found so far and my problems with them:
command 'lpr'
import subprocess
lpr = subprocess.Popen("usr/bin/lpr", stdin=subprocess.PIPE) # on some distros the command is 'lp'
lpr.stdin.write("hello world\n")
lpr.stdin.close()
Relies on the printer propagation via CUPS.
python module pycups
import cups
with open("/home/user/Documents/some.txt", "w") as f:
f.write("hello world\n")
conn = cups.Connection()
conn.printFile("test_printer", "/home/user/Documents/some.txt", "some_title", {})
Before I can use a printer, I'll have to add it first, which in turn relies on the propagation via CUPS.
Also I didn't get conn.addPrinter() to work.
python module python-escpos / python-printer-escpos
import escpos.printer
p = escpos.printer.Network("192.168.1.2", port=631) # port 9100 seems not to work.
p.text("hello world\n")
p.close()
Probably the most promising approach ... unfortunately it doesn't print anything and throws an exception on closing.
# The traceback was produced in the interactive shell.
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/user/.local/lib/python3.6/site-package/escpos/printer.py", line 214, in close
self.device.shutdown(socket.SHUT_RDWR)
OSError: [Errno 107] Transport endpoint is not connected
python module pkipplib / pyipptool
Unfortunately, there seems not to be a working python3 library that implements the Internet Printing Protocol (IPP) in 2018.
I use python 3.6.7.
The print server uses CUPS 2.2.1.
Not being a Python programmer, I cannot provide any sample code.
But I can give you some other hints:
Your assumption, that "in theory, [....] just send correctly formatted data to the IP address + port" is wrong.
If you send something, you have to "talk IPP" to the CUPS server (yes, via the IP address + port 631). But just sending a file is so much less than talking IPP.
Else, you could use 'netcat IPaddress port-no < filename' to print to any CUPS queue (which would be a huge security issue).
So you HAVE to use some IPP-capable library, if you want to integrate your program with IPP/CUPS
One alternative could be that you let your program do the "IPP talk to CUPS" by a CLI tool which is capable of doing so.
Have a look at the ippsample code of the Printer Working Group (PWG) which designed the IPP. That is in "beta" still but already fully usable. All its binaries are command line (CLI) utilities:
It provides the ippfind helper tool. If you run it without any parameters, it will print a list of available IPP Services (print servers and/or printer devices) by printing their respective IPP URIs.
It provides an ippserver command line, which can start up a fully-fledged, you guessed it, IPP Server exposing any feature you want.
Then there is ipptool included as an IPP Client. You could run 'ipptool -f myprintfile -t -v ipp://cupsserver/printers/test_printer print-job.test' to send "myprintfile" to the queue "test_printer" on "cupsserver" (given with example IPP URI ipp://cupsserver/printers/test_printer) and watch it talk IPP to CUPS while it does so.
See also my ASCIIcast "[TUTORIAL] IPP Sample Software (made with an AppImage)" here.
{https://asciinema.org/a/155588 }. Hint: if it plays too fast to follow and understand the screens in time, use the 'pause' button, read at your own speed, then resume playing.
I'm trying to develop a server script using python 3.4 that runs perpetually and responds to client requests on up to 5 separate ports. My preferred platform is Debian 8.0. The platform currently runs on a virtual machine in the cloud. My script works fine when I run it off the command line - I need to now (1) keep it running once I log off the server and (2) keep several ports open through the script so that a windows client can connect to them.
For (1),
After trying several options [I tried using upstart, added the script to rc.local, used nohup with & to run it off the terminal, etc] that didn't seem to work, I eventually found something that does seem to keep the script running, even if it's not very elegant - I wrote an hourly cron script that checks to see if the script is running in the process list, and if not, to execute it.
Whenever I login to the VM now, I see the following output when I type 'ps -ef':
root 22007 21992 98 Nov10 14-12:52:59 /usr/bin/python3.4 /home/userxyz/cronserver.py
I assume that the script is running based on the fact that there is an active process in the system. I mention this part because I suspect that there could be a correlation with part (2) of my issue.
For (2),
The script is supposed to open ports 49100 - 49105 and listen for connection requests, etc. When I run the script from the terminal, zenmap from my client machine verifies that these ports are open. However, when the cron job initiates the script, these ports don't seem to stay open. My windows client program can't connect to the script either.
The python code I use for listening to a port:
f = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
f.bind((serviceIP, 49101))
f.listen(5)
while True:
scName, address = f.accept()
[code to handle request]
scName.shutdown(socket.SHUT_WR)
scName.close()
Any insight or assistance would be greatly appreciated!
What you ask is not easy because it depends on a variety of factors:
What is the frequency of the data received?
How many clients are expected to connect to this server?
Is there a chance two clients try to connect at the same time?
How long it takes to handle some received data?
What do you need to do with your data?
Write to a database?
Write to a file?
Calculate something?
Etc.
Depending on your answer you'll have some design decisions to make for your solution.
But since you need an answer, here's a hack that represent a way to do things:
import socketserver
import threading
import datetime
class SleepyGaryReceptionHandler(socketserver.BaseRequestHandler):
log_file_name = "/tmp/sleepygaryserver.log"
def handle(self):
# self.request is defined in BaseRequestHandler
data_received = self.request.recv(1024)
# self.client_address is also defined in BaseRequestHandler
sender_address = self.client_address[0]
# This is where you are supposed to do something with your data
# This is an example
self.write_to_log('Someone from {} sent us "{}"'.format(sender_address,
data_received))
# A way to stop the server from going on forever
# But you could do this other ways but it depends what condition
# should cause the shutdown
if data_received.startswith(b"QUIT"):
finishing_thread = threading.Thread(target=self.finish_in_another_thread)
finishing_thread.start()
# This will be called in another thread to terminate the server
# self.server is also defined in BaseRequestHandler
def finish_in_another_thread(self):
self.write_to_log("Shutting down the server")
self.server.shutdown()
# Write something (with a timestamp) to a text file so that we
# know something is happenning
def write_to_log(self, message):
timestamp = datetime.datetime.now()
timestamp_text = timestamp.isoformat(sep=' ', timespec='seconds')
with open(self.log_file_name, mode='a') as log_file:
log_file.write("{}: {}\n".format(timestamp_text, message))
service_address = "localhost"
port_number = 49101
server = socketserver.TCPServer((service_address, port_number),
SleepyGaryReceptionHandler)
server.serve_forever()
I'm using here the socketserver module instead of listening directly at a socket. This standard library module has been written to simplify writing a server. so use it!
All I do here is write to a text file what has been received. You would have to adapt it to your use.
But to have it running continuously use a cron job but to start it at the startup of the computer. Since this script will block until the server is stopped, we have to run it in the background. It would look something like that:
#reboot /usr/bin/python3 /home/sleepygary/sleppys_server.py &
I have tested it and after 5 hours it still does his thing.
Now like I said, it is a hack. If you want to go all the way and do things like any other services on your computer you have to program it in a certain way. You can find more information on this page: https://www.freedesktop.org/software/systemd/man/daemon.html
I'm really tired so there may be some errors here and there.
Use case: There is a certain file located on a remote server. Instead of hard coding the path to that file in my program I would like to be prompted by the program to let me specify the path to that directory on the remote server. This will help in program portability. I am able to connect to remote server in pyCharm 4.5 professional edition. Using SFTP to connect to remote server in pyCharm. Password or keyfile is not an issue to be concerned with at least for now.
Question: the function raw_input() works for local interpreter. But what method do I use to prompt the user to enter the directory path to a file located in a remote server?
For now I am hard-coding the file path in the program like
input_file="/home/ashish/PyCharm_proj/raw_data/all_user_and_tweets_only_raw.csv"
I also tried the following code which off course does not work when executed on the remote server
import os,sys
user_input = raw_input("Enter the path of your file (use \: ")
assert os.path.exists(user_input), "I did not find the file at, "+str(user_input)
input_file = open(user_input,'r+')
print("Hooray we found your file!")
Similar questions are 1,2,3,4 but I could not find anything relevant that satisfies my use case. Any suggestions to solve this?
To validate the file exists on remote host/server you need a way to connect to that host. There are many different ways depending on your situation.
From your description above it looks like you have ssh access to the
remote system? In this case Paramiko can be used to connect via ssh
and execute remote command
If the remote host files are published on a website via HTTP you can
verify it via URL, but beware that this may not reflect the remote host
full path since it depends on HTTP root.
So it really depends on your case.
If using paramiko, one of the easiest way is to use SFTP class. Something like this:
ssh_client = paramiko.SSHClient()
ssh_client.connect(host, port, user, password)
sftp = ssh_client.open_sftp()
file_stat = sftp.stat(path) # can use stat
try:
sftp_obj1 = sftp.file(path) # or use file
sftp_obj2 = sftp.open(path) # or use open
except:
print "Error! File not found!"
So, the question was a bit unclear at first. OP was ultimately looking for a way to give input to his script about the location (known) of a file on a remote server.
OP tried raw_input but got an unspecified error.
Further discussion in comments reveals the original approach was correct for this use case. The error was in an unrelated section of code, where OP used the same identifier for the input string and the file object, resulting in trying to open the file object.