What is the Python 3 equivalent of python -m SimpleHTTPServer?
From the docs:
The SimpleHTTPServer module has been merged into http.server in Python 3.0. The 2to3 tool will automatically adapt imports when converting your sources to 3.0.
So, your command is python -m http.server, or depending on your installation, it can be:
python3 -m http.server
The equivalent is:
python3 -m http.server
Using 2to3 utility.
$ cat try.py
import SimpleHTTPServer
$ 2to3 try.py
RefactoringTool: Skipping implicit fixer: buffer
RefactoringTool: Skipping implicit fixer: idioms
RefactoringTool: Skipping implicit fixer: set_literal
RefactoringTool: Skipping implicit fixer: ws_comma
RefactoringTool: Refactored try.py
--- try.py (original)
+++ try.py (refactored)
## -1 +1 ##
-import SimpleHTTPServer
+import http.server
RefactoringTool: Files that need to be modified:
RefactoringTool: try.py
Like many *nix utils, 2to3 accepts stdin if the argument passed is -. Therefore, you can test without creating any files like so:
$ 2to3 - <<< "import SimpleHTTPServer"
In addition to Petr's answer, if you want to bind to a specific interface instead of all the interfaces you can use -b or --bind flag.
python -m http.server 8000 --bind 127.0.0.1
The above snippet should do the trick. 8000 is the port number. 80 is used as the standard port for HTTP communications.
As everyone has mentioned http.server module is equivalent to python -m SimpleHTTPServer.
But as a warning from https://docs.python.org/3/library/http.server.html#module-http.server
Warning: http.server is not recommended for production. It only implements basic security checks.
Usage
http.server can also be invoked directly using the -m switch of the interpreter.
python -m http.server
The above command will run a server by default on port number 8000. You can also give the port number explicitly while running the server
python -m http.server 9000
The above command will run an HTTP server on port 9000 instead of 8000.
By default, server binds itself to all interfaces. The option
-b/--bind specifies a specific address to which it should bind. Both IPv4 and IPv6 addresses are supported. For example, the following
command causes the server to bind to localhost only:
python -m http.server 8000 --bind 127.0.0.1
or
python -m http.server 8000 -b 127.0.0.1
Python 3.8 version also supports IPv6 in the bind argument.
Directory Binding
By default, server uses the current directory. The option -d/--directory specifies a directory to which it should serve the files. For example, the following command uses a specific directory:
python -m http.server --directory /tmp/
Directory binding is introduced in python 3.7
In one of my projects I run tests against Python 2 and 3. For that I wrote a small script which starts a local server independently:
$ python -m $(python -c 'import sys; print("http.server" if sys.version_info[:2] > (2,7) else "SimpleHTTPServer")')
Serving HTTP on 0.0.0.0 port 8000 ...
As an alias:
$ alias serve="python -m $(python -c 'import sys; print("http.server" if sys.version_info[:2] > (2,7) else "SimpleHTTPServer")')"
$ serve
Serving HTTP on 0.0.0.0 port 8000 ...
Please note that I control my Python version via conda environments, because of that I can use python instead of python3 for using Python 3.
Just wanted to add what worked for me:
python3 -m http.server 8000 (you can use any port number here except the ones which are currently in use)
Related
Is it possible to have a one line command in python to do a simple ftp server? I'd like to be able to do this as quick and temporary way to transfer files to a linux box without having to install a ftp server. Preferably a way using built in python libraries so there's nothing extra to install.
Obligatory Twisted example:
twistd -n ftp
And probably useful:
twistd ftp --help
Usage: twistd [options] ftp [options].
WARNING: This FTP server is probably INSECURE do not use it.
Options:
-p, --port= set the port number [default: 2121]
-r, --root= define the root of the ftp-site. [default:
/usr/local/ftp]
--userAnonymous= Name of the anonymous user. [default: anonymous]
--password-file= username:password-style credentials database
--version
--help Display this help and exit.
Check out pyftpdlib from Giampaolo Rodola. It is one of the very best ftp servers out there for python. It's used in google's chromium (their browser) and bazaar (a version control system). It is the most complete implementation on Python for RFC-959 (aka: FTP server implementation spec).
To install:
pip3 install pyftpdlib
From the commandline:
python3 -m pyftpdlib
Alternatively 'my_server.py':
#!/usr/bin/env python3
from pyftpdlib import servers
from pyftpdlib.handlers import FTPHandler
address = ("0.0.0.0", 21) # listen on every IP on my machine on port 21
server = servers.FTPServer(address, FTPHandler)
server.serve_forever()
There's more examples on the website if you want something more complicated.
To get a list of command line options:
python3 -m pyftpdlib --help
Note, if you want to override or use a standard ftp port, you'll need admin privileges (e.g. sudo).
Why don't you instead use a one-line HTTP server?
python -m SimpleHTTPServer 8000
will serve the contents of the current working directory over HTTP on port 8000.
If you use Python 3, you should instead write
python3 -m http.server 8000
See the SimpleHTTPServer module docs for 2.x and the http.server docs for 3.x.
By the way, in both cases the port parameter is optional.
The answers above were all assuming your Python distribution would have some third-party libraries in order to achieve the "one liner python ftpd" goal, but that is not the case of what #zio was asking. Also, SimpleHTTPServer involves web broswer for downloading files, it's not quick enough.
Python can't do ftpd by itself, but you can use netcat, nc:
nc is basically a built-in tool from any UNIX-like systems (even embedded systems), so it's perfect for "quick and temporary way to transfer files".
Step 1, on the receiver side, run:
nc -l 12345 | tar -xf -
this will listen on port 12345, waiting for data.
Step 2, on the sender side:
tar -cf - ALL_FILES_YOU_WANT_TO_SEND ... | nc $RECEIVER_IP 12345
You can also put pv in the middle to monitor the progress of transferring:
tar -cf - ALL_FILES_YOU_WANT_TO_SEND ...| pv | nc $RECEIVER_IP 12345
After the transferring is finished, both sides of nc will quit automatically, and job done.
For pyftpdlib users. I found this on the pyftpdlib website. This creates anonymous ftp with write access to your filesystem so please use with due care. More features are available under the hood for better security so just go look:
sudo pip3 install pyftpdlib
python3 -m pyftpdlib -w
## updated for python3 Feb14:2020
Might be helpful for those that tried using the deprecated method above.
sudo python -m pyftpdlib.ftpserver
apt-get install python3-pip
pip3 install pyftpdlib
python3 -m pyftpdlib -p 21 -w --user=username --password=password
-w = write permission
-p = desired port
--user = give your username
--password = give your password
Install:
pip install twisted
Then the code:
from twisted.protocols.ftp import FTPFactory, FTPRealm
from twisted.cred.portal import Portal
from twisted.cred.checkers import AllowAnonymousAccess, FilePasswordDB
from twisted.internet import reactor
reactor.listenTCP(21, FTPFactory(Portal(FTPRealm('./'), [AllowAnonymousAccess()])))
reactor.run()
Get deeper:
http://twistedmatrix.com/documents/current/core/examples/
The simpler solution will be to user pyftpd library. This library allows you to spin Python FTP server in one line. It doesn’t come installed by default though, but we can install it using simple apt command
apt-get install python-pyftpdlib
now from the directory you want to serve just run the pythod module
python -m pyftpdlib -p 21
I dont know about a one-line FTP server, but if you do
python -m SimpleHTTPServer
It'll run an HTTP server on 0.0.0.0:8000, serving files out of the current directory. If you're looking for a way to quickly get files off a linux box with a web browser, you cant beat it.
I want to run an HTML file in localhost:8080, I'm using the command:
python3 -m http.server
Problem is when I try to open localhost:8080 it downloads the HTML file instead of displaying it.
Problem is when I try to open localhost:8080 it downloads the HTML file instead of displaying it.
You want to open http://localhost:8000 instead.
When you use the command you mentioned, python3 -m http.server, it defaults to port 8000, as explained in its startup output:
$ python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
We don't know what different server you have running on port 8080, but apparently it doesn't put Content-type: text/html in its output headers.
viewing webserver http headers
It's easy to view those headers, e.g. with wget use the -S switch.
You need to add an option that'll put your website on port 8080 because the http.server command defaults to port 8000.
You can do this using:
python3 -m http.server 8080
Then when you go to 0.0.0.0:8080 it should show you your webpage instead of a download prompt.
Also, you might have another instance of http.server running on port 8080.
You can find the PID of this task using:
ps -A | grep "python3"
Which should show something that looks like this:
Then you could kill it using:
kill <PID-FOR-PYTHON3-INSTANCE>
Or in my case the task that's running on port 8080 is:
kill 6856
Or, if you don't mind, just kill all Python3 tasks using:
killall python3
Which in my case would kill both Python3 tasks.
WARNING: be very, VERY careful before running the killall command, because this command will NOT save your work.
UPDATE: that blurry section in the picture is my username, I wasn't sure if it would be against the rules to include it.
Good luck.
I want to integrate my project into Travis-CI. My project involved a Flask web-server in Python with a postgresql database. All my tests use a web server running in debug mode. I'm trying to get this set up properly on Travis-CI and am having some troubles.
I'm building and testing under python 2.7 and 3.4, and the problem is my web server does not appear to start during the 3.4 build. The build for 2.7 starts first, runs fine, and all my tests pass, however the web server fails to start in the 3.4 build. When I run each build individually, both the 2.7 and 3.4 builds work fine and all tests pass. Is there a conflict between the web servers for each build? Here is my travis.yml file.
language: python
sudo: false
python:
- '2.7'
- '3.4'
os:
- linux
services:
- postgresql
- memcached
addons:
postgresql: '9.4'
apt:
packages:
xvfb
nano
branches:
- master
before_install:
- wget http://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh -O ~/miniconda.sh
- bash ~/miniconda.sh -b -p $HOME/miniconda
- export PATH="$HOME/miniconda/bin:$PATH"
- conda update --yes conda
install:
- conda create --yes -n test_env python=$TRAVIS_PYTHON_VERSION pip numpy scipy matplotlib ipython --quiet
- source activate test_env
- pip install -r requirements.txt --quiet
- pip install psycopg2 --quiet
- pip install blinker --quiet
- pip install nose --quiet
- pip install coverage --quiet
- pip install pytest --quiet
- pip install pytest-cov --quiet
- pip install pytest-sugar --quiet
- python setup.py install
before_script:
- export MANGA_LOCALHOST=1
- export PYTHONPATH=$PYTHONPATH:$TRAVIS_BUILD_DIR/python
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start
- sleep 3
- sh $TRAVIS_BUILD_DIR/bin/setup_travis
# make a local port based on python version, e.g. 5027 or 5034
- export LOCAL_MARVIN_PORT=50${TRAVIS_PYTHON_VERSION/.}
# start the local web server on port 50XX
- $TRAVIS_BUILD_DIR/bin/run_marvin -l -d -p $LOCAL_MARVIN_PORT > /dev/null &
- sleep 10
# list the processes running
- lsof -Pnl +M -i4
# test the web server is running
- curl http://localhost:$LOCAL_MARVIN_PORT/marvin2/api/general/getroutemap/
script:
- py.test python/marvin/tests -v --cov python/marvin --cov-report html
after_success:
- coveralls
Originally the local web server was running on port 5000, which I thought would be ok since each python build should be independent. It didn't work then and thought it might be related to the port, so I made each web server run on a unique port, but that hasn't fixed the problem. I'm printing various things as checks
The 2.7 build says the web server is running on 5027 and my curl produces output.
$ lsof -Pnl +M -i4
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
Xvfb 3516 1000 1u IPv4 67036287 0t0 TCP *:6099 (LISTEN)
python 3698 1000 5u IPv4 67163206 0t0 TCP 127.0.0.1:5027 (LISTEN)
python 3698 1000 7u IPv4 67154596 0t0 TCP 172.17.0.5:55988->155.101.19.34:443 (ESTABLISHED)
python 3698 1000 8u IPv4 67162470 0t0 TCP 172.17.0.5:55964->155.101.19.34:80 (ESTABLISHED)
python 3713 1000 5u IPv4 67163206 0t0 TCP 127.0.0.1:5027 (LISTEN)
python 3713 1000 7u IPv4 67154596 0t0 TCP 172.17.0.5:55988->155.101.19.34:443 (ESTABLISHED)
python 3713 1000 8u IPv4 67162470 0t0 TCP 172.17.0.5:55964->155.101.19.34:80 (ESTABLISHED)
$ curl http://localhost:$LOCAL_MARVIN_PORT/marvin2/api/general/getroutemap/
--------------------------------------------------------------------------------
INFO in __init__ [/home/travis/build/sdss/marvin/python/marvin/web/__init__.py:146]:
Loading config file: /home/travis/build/sdss/marvin/python/marvin/web/configuration/localhost.cfg
--------------------------------------------------------------------------------
WARNING:root: * CAUTION: flask-profiler is working without basic auth!
WARNING:werkzeug: * Debugger is active!
{
"data": null,
"error": null,
"inconfig": {},
"status": 1,
"traceback": null,
...
}
It proceeds to go on and run all the tests. However, my 3.4 build seems to fail to start the web server on port 5034 with no indication why. The ports are indeed set differently.
$ lsof -Pnl +M -i4
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
Xvfb 3532 1000 1u IPv4 34279725 0t0 TCP *:6099 (LISTEN)
$ curl http://localhost:$LOCAL_MARVIN_PORT/marvin2/api/general/getroutemap/
curl: (7) couldn't connect to host
The command "curl http://localhost:$LOCAL_MARVIN_PORT/marvin2/api/general/getroutemap/" failed and exited with 7 during .
Again, when I run each build individually, both 2.7 and 3.4 build successfully, run all tests and pass. Could it have something to do with how I'm dumping the standard out of the web server into /dev/null? Should I be doing something differently there? Is each build not exactly independent of one another?
Update: I just tried it without the /dev/null and got the same reesult. Also this time, the python 3.4 was ahead of the 2.7 build, and the 3.4 build successfully started the web server and ran the tests. The 2.7 build was unable to start the web server and was somehow blocked by the other build.
I solved this by increasing my sleep time from 10 to 20. Apparently, 10 seconds was too short a time to allow the web server to start up.
When I run python -m SimpleHTTPServer 8000 or python -m CGIHTTPServer 8000 in my shell I am hosting the content of my current directory to the internet.
I would like to make the following cgi_script.py work correctly using the above command in the command line when I browse to 192.xxx.x.xx:8000/cgi_script.py
#!/usr/bin/env python
print "Content-Type: text/html"
print
print """\
<html>
<body>
<h2>Hello World!</h2>
</body>
</html>
"""
But this script is displayed literally and not only the "Hello World!" part.
Btw I changed the file permissions to 755 for cgi_script.py as well as the folder I am hosting it from.
Try with python -m CGIHTTPServer 8000.
Note that you have to move the script to a cgi-bin or htbin directory in order to be runnable.
SO doesn't allow me to comment so I'm adding this as a separate answer, addition to rodrigo's.
You can use another parameter cgi_directories which defaults to ['/cgi-bin', '/htbin']. More info here
In Python3 the command line is simply
python3 -m http.server --cgi 8000
When I ran into this issue I found that depending on which directory you are in when you run the python -m CGIHTTPServer 8000 command yields different results. When attempting to run the command while in the cgi-bin directory the browser continued to return the raw script code. once I cd'ed one level higher and ran the python -m CGIHTTPServer 8000 command again my script began executing.
#Bentley4 -ifyou are still not able to do,
try importing cgi.
#!C:\Python34\python.exe -u
import cgi
print ("Content-type:text/html")
HTH
This work for me, run the python -m CGIHTTPServer 8000 command same menu level with cgi-bin,and move cgi_script.py into cgi-bin folder.In browser type http://localhost:8000/cgi-bin/cgi_script.py
Is it possible to have a one line command in python to do a simple ftp server? I'd like to be able to do this as quick and temporary way to transfer files to a linux box without having to install a ftp server. Preferably a way using built in python libraries so there's nothing extra to install.
Obligatory Twisted example:
twistd -n ftp
And probably useful:
twistd ftp --help
Usage: twistd [options] ftp [options].
WARNING: This FTP server is probably INSECURE do not use it.
Options:
-p, --port= set the port number [default: 2121]
-r, --root= define the root of the ftp-site. [default:
/usr/local/ftp]
--userAnonymous= Name of the anonymous user. [default: anonymous]
--password-file= username:password-style credentials database
--version
--help Display this help and exit.
Check out pyftpdlib from Giampaolo Rodola. It is one of the very best ftp servers out there for python. It's used in google's chromium (their browser) and bazaar (a version control system). It is the most complete implementation on Python for RFC-959 (aka: FTP server implementation spec).
To install:
pip3 install pyftpdlib
From the commandline:
python3 -m pyftpdlib
Alternatively 'my_server.py':
#!/usr/bin/env python3
from pyftpdlib import servers
from pyftpdlib.handlers import FTPHandler
address = ("0.0.0.0", 21) # listen on every IP on my machine on port 21
server = servers.FTPServer(address, FTPHandler)
server.serve_forever()
There's more examples on the website if you want something more complicated.
To get a list of command line options:
python3 -m pyftpdlib --help
Note, if you want to override or use a standard ftp port, you'll need admin privileges (e.g. sudo).
Why don't you instead use a one-line HTTP server?
python -m SimpleHTTPServer 8000
will serve the contents of the current working directory over HTTP on port 8000.
If you use Python 3, you should instead write
python3 -m http.server 8000
See the SimpleHTTPServer module docs for 2.x and the http.server docs for 3.x.
By the way, in both cases the port parameter is optional.
The answers above were all assuming your Python distribution would have some third-party libraries in order to achieve the "one liner python ftpd" goal, but that is not the case of what #zio was asking. Also, SimpleHTTPServer involves web broswer for downloading files, it's not quick enough.
Python can't do ftpd by itself, but you can use netcat, nc:
nc is basically a built-in tool from any UNIX-like systems (even embedded systems), so it's perfect for "quick and temporary way to transfer files".
Step 1, on the receiver side, run:
nc -l 12345 | tar -xf -
this will listen on port 12345, waiting for data.
Step 2, on the sender side:
tar -cf - ALL_FILES_YOU_WANT_TO_SEND ... | nc $RECEIVER_IP 12345
You can also put pv in the middle to monitor the progress of transferring:
tar -cf - ALL_FILES_YOU_WANT_TO_SEND ...| pv | nc $RECEIVER_IP 12345
After the transferring is finished, both sides of nc will quit automatically, and job done.
For pyftpdlib users. I found this on the pyftpdlib website. This creates anonymous ftp with write access to your filesystem so please use with due care. More features are available under the hood for better security so just go look:
sudo pip3 install pyftpdlib
python3 -m pyftpdlib -w
## updated for python3 Feb14:2020
Might be helpful for those that tried using the deprecated method above.
sudo python -m pyftpdlib.ftpserver
apt-get install python3-pip
pip3 install pyftpdlib
python3 -m pyftpdlib -p 21 -w --user=username --password=password
-w = write permission
-p = desired port
--user = give your username
--password = give your password
Install:
pip install twisted
Then the code:
from twisted.protocols.ftp import FTPFactory, FTPRealm
from twisted.cred.portal import Portal
from twisted.cred.checkers import AllowAnonymousAccess, FilePasswordDB
from twisted.internet import reactor
reactor.listenTCP(21, FTPFactory(Portal(FTPRealm('./'), [AllowAnonymousAccess()])))
reactor.run()
Get deeper:
http://twistedmatrix.com/documents/current/core/examples/
The simpler solution will be to user pyftpd library. This library allows you to spin Python FTP server in one line. It doesn’t come installed by default though, but we can install it using simple apt command
apt-get install python-pyftpdlib
now from the directory you want to serve just run the pythod module
python -m pyftpdlib -p 21
I dont know about a one-line FTP server, but if you do
python -m SimpleHTTPServer
It'll run an HTTP server on 0.0.0.0:8000, serving files out of the current directory. If you're looking for a way to quickly get files off a linux box with a web browser, you cant beat it.