I am running the following code and it terminates with the following message. Please refer to the screenshot.
import zmq
context = zmq.Context()
socket = context.socket(zmq.SUB)
socket.connect('tcp://0.0.0.0:5555')
zmq is the Python binding for ØMQ. There are links for Python.exe stopped working, however the solutions appear to be problem specific. Please suggest the way forward. Thanks in advance.
Using ZeroMQ inside quasi-cluster-enabled clients requires more care:
Be it iPython, Jupyter or even Spyder, these python WYSIWYG- or IDE-frontends use ZeroMQ on their own internally, and quite intensively, to communicate between the GUI in "terminal" or the "notebook" and the backend python-engine(s).
So a double care is needed. Every port-mapping is even more delicate.
As one might read, O/S reports that the problems are on the backend-engine, that went mad, not on the GUI frontend.
Anyway,rather do not use bewildered constructors like tcp://0.0.0.0:<port#> or tcp://*:<port#>
Documentation explicitly advises another approach how to safely .connect() to localhost ( sure, that port was still free from iPython / Jupyter / Spyder own use ):
>>> print zmq.Socket.connect.__doc__
s.connect(addr)
Connect to a remote 0MQ socket.
Parameters
----------
addr : str
The address string. This has the form 'protocol://interface:port',
for example 'tcp://127.0.0.1:5555'. Protocols supported are
tcp, upd, pgm, inproc and ipc. If the address is unicode, it is
encoded to utf-8 first.
>>>
Related
I have a dot-matrix printer LX-300 connected to my computer through the network. How do I send a raw string with ESCP characters directly to my printer in Python?
The computer is connected to the printer through another computer. I need to send a raw string because LX-300 image printing result is blurry.
The Problem
To send data down this route:
Client computer ---> Server (Windows machine) ---> printer (dot-matrix)
...and to not let Windows mess with the data; instead to send the raw data, including printer control codes, straight from the client computer.
My Solution
Here's how I solved a near-identical problem for a small in-house database application:
Step 1) Make the printer network-accessible without Windows getting its fingers in the data routed to it. I accomplished this by installing the printer using the "Generic/Text Only" driver, then installing
RawPrintServer on the Windows machine connected to the printer.
Step 2) Send raw data over the network to the TCP/IP port specified when you set up RawPrintServer (default is 9100). There are various ways to do that, here's what I did:
data = b"\x1B#A String To Print\x1B#" # be sure to use the right codes for your printer
ip_addr = 123.123.123.123 # address of the machine with the printer
port = 9100 # or whatever you set it to
s = socket.socket()
try:
s.connect((ip_addr, port))
s.send(data)
except:
# deal with the error
finally:
s.close()
Background
I thought about the problem in two parts:
Client machine: spitting out the data I need from Python with the correct formatting/control codes for my printer, and sending it across the network
Print server machine: transmitting the data to the locally connected printer
Number 1 is the easy part. There are actually some libraries in PyPI that may help with all the printer codes, but I found most of them are aimed at the little point-of-sale label printers, and were of limited use to me. So I just hard-coded what I needed into my Python program.
Of course, the way you choose to solve number 2 will effect how you send the data from Python. I chose the TCP/IP route to avoid dealing with Samba and Windows print issues.
As you probably discovered, Windows normally tries very hard to convert whatever you want to print to a bitmap and run the printer in graphics mode. We can use the generic driver and dump the data straight into the (local) printer port in order to prevent this.
The missing link, then, is getting from the network to the local printer port on the machine connected to the printer. Again, there are various ways to solve this. You could attempt to access the Windows printer share in some way. If you go the TCP/IP route like I did, you could write your own print server in Python. In my case, the RawPrintServer program "just worked" so I didn't investigate any further. Apparently all it does is grab incoming data from TCP port 9100 and shove it into the local printer port. Obviously you'll have to be sure the firewall isn't blocking the incoming connections on the print server machine. This method does not require the printer to be "shared" as far as Windows is concerned.
Depending on your situation (if you use DHCP), you might need to do some extra work to get the server's IP address in Python. In my case, I got the IP for free because of the peculiarity of my application.
This solution seems to be working out very well for me. I've got an old Panasonic printer running in Epson ESC/P compatibility mode connected to a Windows 7 machine, which I can print to from any other computer on the local network. Incidentally, this general idea should work regardless of what OS the client computer is running.
Ultimately, you will need and want to write your own wrapper/script to do this. And since you are using a distribution of Linux, this is relatively easy.
On a Linux OS, the simplest way to issue a print job is to open a subprocess to the lpr. Generally, using lpr lets you access the printer without the need to be logged in as root (being a superuser), which is desirable considering the amount of damage that can be done while logged in as a "superuser".
Code like the following:
import subprocess
lpr = subprocess.Popen("/usr/bin/lpr", stdin=subprocess.PIPE)
lpr.stdin.write(data_to_send_to_printer)
Should be a good jumping off point for you. Essentially, this code should allow you to accomplish what you need.
Be careful though; depending on your privilege levels, a call to open a subprocess might need root level/Superuser permissions.
Subprocesses generally inherit the User IDs and access rights by the user that is running the command. For example, if the subprocess is created by a root user, then you will need root user/Superuser rights to access that subprocess.
For more information, check out the hyperlinks I've included in the post.
Good luck!
I am creating a python application using twisted which reads lines from a serial port.
In order to (unit)test that app without having to connect an actual device to the serial port (also on pc's without an actual serial port) I would like to create a python script/app that sets up a virtual serial port and writes to it, so the twisted app can connect to the other end of the virtual serial port and read from it. This way I can write some unittests.
I found this is possible using pseudo terminals in linux. I also found a working example script on https://askubuntu.com/questions/9396/virtual-serial-port-for-testing-purpose.
I would like to change that script to a class on which I can call a write method to write data to the serial port, and then test the twisted app.
This example script does a lot of stuff with poll and select and a linux stty command which I don't really understand. I hope someone can fill the gap in my knowledge or provide some hints.
Cheers,
Dolf.
In addition to what Jean-Paul Calderone said (which was the correct answer mostly), I also made the following script in python, using socat.
This can be imported and instantiated into an interpreter, and then you can use it's writeLine method to write data to a (vritual) serial port, which is connected through socat to another (virtual) serial port, on which another twisted app can be listening. But as Jean-Paul Calderone said: if it's just unittesting you want, you don't really need to do this stuff. Just read the docs he mentioned.
import os, subprocess, serial, time
from ConfigParser import SafeConfigParser
class SerialEmulator(object):
def __init__(self,configfile):
config=SafeConfigParser()
config.readfp(open(configfile,'r'))
self.inport=os.path.expanduser(config.get('virtualSerialPorts','inport'))
self.outport=os.path.expanduser(config.get('virtualSerialPorts','outport'))
cmd=['/usr/bin/socat','-d','-d','PTY,link=%s,raw,echo=1'%self.inport,'PTY,link=%s,raw,echo=1'%self.outport]
self.proc=subprocess.Popen(cmd,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
time.sleep(3)
self.serial=serial.Serial(self.inport)
self.err=''
self.out=''
def writeLine(self,line):
line=line.strip('\r\n')
self.serial.write('%s\r\n'%line)
def __del__(self):
self.stop()
def stop(self):
self.proc.kill()
self.out,self.err=self.proc.communicate()
You don't need a pty to test your protocol. You don't even need any kind of file descriptor. Follow the guidelines at http://twistedmatrix.com/documents/current/core/howto/trial.html, particularly the Testing a protocol section.
A better approach is probably to use a software null modem emulator.
You can get it from github for linux and from sourceforge for windows.
On linux it is called tty0tty and you simply type
make
to build everything. Then you would need to type
sudo insmod module/tty0tty.ko
to install the virtual driver and
./pts/tty0tty
to launch the application, which opens you 2 virtual ports: /dev/pts/4 and /dev/pts/6.
You can then open the /dev/pts/4 serial port in your python unit tests and open the /dev/pts/6 in your application.
In your python unit test, you would just type something like:
import serial
ser = serial.Serial('/dev/pts/4', 19200)
I have a device with a built-in USB/Serial adapter (shows up as a Prolific PL2303). The device documentation provides full details on how to communicate with it, and provides a sample Windows app. However, I need to use it on Linux - ideally with Python but I'm not too precious about that.
The device docs state the device runs at 9600, 8N1 with half duplex. The Windows app works fine - device works fine (so I know it's not a device problem). However, I can't communicate with it using Python on Linux. I'm using pySerial, and I've tried a similar (full duplex, also PL2303) device which works fine.
I've tried several combinations of setting xonxoff, rtscts etc. I've also tried RTS toggling using setRTS(True) and checking for CTS and DSR etc - gets all return False. I can successfully open the device using pySerial (I can see activity light flashing - simple but effective test) and pySerial complains if you unplug it during reads/writes.
Doesn't seem to matter what flags/lines I set or what data I send, always get the same result.
>>> s=serial.Serial()
>>> s.port('/dev/ttyUSB1')
>>> s.open()
>>> s
Serial<id=0x7fe94b533b50, open=True>(port='/dev/ttyUSB1', baudrate=9600, bytesize=8, parity='N', stopbits=1, timeout=3, xonxoff=0, rtscts=0, dsrdtr=0)
>>> s.write('\2CMD2292\r')
>>> s.inWaiting()
0
>>> s.setRTS(True)
>>> s.getCTS()
False
(several iterations of above with different flags).
Ignore the data in the write command - that's just a status check command. Doesn't matter what goes there, the device should either respond with an answer or an error.
I've even resorted to closing and re-opening the device in between setting various ctsrts flags etc., and unplugging / replugging it to force resets. As above it continues to work fine using the Windows test app. I can't use Portmon etc. to sniff the Windows port traffic as it's a 64bit Win7 install and I don't currently have time to build an XP machine.
Any thoughts?
UPDATE: I've also tried all of the above using Python on the same Windows box that the demo app works on. It definitely opens the port and communicates, but again no info back regardless of what's written.
UPDATE2: It looks like it might be device-driver related. Some additional background research suggests that some PL2303 chips have functionality to support half-duplex, but this isn't supported by the Linux drivers. The Windows demo app comes with a dedicated device driver and the app doesn't work on a clean test machine using default Windows drivers. This makes me think that while I can connect to it successfully through Python, I can't control the duplex comms (e.g. even in an STX/ETX way) and therefore this might be a hopeless case. sigh.
UPDATE3: Thanks for the comments below. However, I couldn't find any way round this. I tried a USB protocol analyser, and I tried disassembling the driver but it just became rather time-consuming, so in the end I took the device apart and after some tinkering I managed to replace the existing usb-serial adapter with a proper PL2303 part - on the device side, it was just a basic 2-wire serial interface so it didn't care what was talking to it. I can't seem to close this question so I'll leave it as-is.
Try
s.flush()
just after your s.write call
I've developed an application that is essentially just a little ftp server with the ability to specify which directory you wish to share on startup. I'm using ftplib for the server because it's sick easy. The only issue I'm having is that if you are behind a router you have to manually forward the ports on your router and I'm finding that it's a little too complicated for my users (aka co-workers/clients).
So I've been looking for a simple solution to open ports but I'm finding that most APIs are too broad and way over my head. Does someone know of a solution that would be relatively simple to implement?
Note: It will really only be used on windows although cross-platform compatibility would be welcomed. If there is a windows only solution that is simpler then I would opt for that.
Thanks!
Simple example for miniupnp. It creates a mapping on the discovered gateway from external port 43210 to the interface connected to port 43210 on the interface connected to the discovered gateway.
import miniupnpc
upnp = miniupnpc.UPnP()
upnp.discoverdelay = 10
upnp.discover()
upnp.selectigd()
port = 43210
# addportmapping(external-port, protocol, internal-host, internal-port, description, remote-host)
upnp.addportmapping(port, 'TCP', upnp.lanaddr, port, 'testing', '')
The protocol you want is called IGD (for Internet Gateway Device) and is based on UPNP. It allows a client program (yours) to discover the router on the network (using UPNP) and then ask it to forward a specific port.
This is supported by most home routers, and the technique is used by a lot of services like BitTorrent or multiPlayer games, bit it's a bit complicated to use or implement. There are several open source libraries that support IGD and one of the simplest one (which is also cross-platform) is "miniupnp": see http://miniupnp.free.fr/
Looks like there are a few options, one being miniupnp. There are also python bindings for GNUPnP here. For windows minupnp will work, or you could go pure python with miranda-upnp.
There is a nice example of the python GNUPnP bindings being used to open ports on a router here.
In that example the lease time is set to 0, which is unlimited. See here for the definition of add_port.
A simple example might be:
#! /usr/bin/python
import gupnp.igd
import glib
from sys import stderr
my_ip = YOUR_IP
igd = gupnp.igd.Simple()
igd.external_ip = None
main = glib.MainLoop()
def mep(igd, proto, eip, erip, port, localip, lport, msg):
if port == 80:
igd.external_ip = eip
main.quit()
def emp(igd, err, proto, ep, lip, lp, msg):
print >> stderr, "ERR"
print >> stderr, err, proto, ep, lip, lp, msg
main.quit()
igd.connect("mapped-external-port", mep)
igd.connect("error-mapping-port", emp)
#igd.add_port("PROTO", EXTERNAL_PORT, INTERNAL_IP, INTERNAL_PORT, LEASE_DURATION_IN_SECONDS, "NAME")
igd.add_port("TCP", 80, my_ip, 8080, 86400, "web")
main.run()
There is an article explaining how to use the Windows IGD COM object with win32com.
I looked for this for many days. I was unable to install miniupnpc using pip for python 3.
I solved this isue with an implementation found here which will work for python 2.
I forked it and make the changes to be used on python 3, you can find it Here
This implementation is by far the simplest I have seen and works well.
I want to be able to reuse some ports, and that's why I'm using setsockopt on my sockets, with the following code:
sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
However, this doesn't really work. I'm not getting a bind error either, but the server socket just isn't responding (it seems to start , but if I try to connect to it, it doesn't enter the select loop). This behaviour appears if the script ended unexpectedly, and if I change the port the server is listening on, everything works again. Can you provide some advice?
EDIT: I renamed the socket to sock. It was just a name I chose for this code snippet.
It appears that SO_REUSEADDR has different semantics on Windows vs Unix.
See this msdn article (particularly the chart below "Using SO_EXCLUSIVEADDRUSE") and this unix faq.
Also, see this python bug discussion, this twisted bug discussion, and this list of differences between Windows and Unix sockets.
setsockopt is a method of a socket object. module socket doesn't have a setsockopt attribute.